Compare commits

...

57 Commits

Author SHA1 Message Date
github-actions[bot]
15153855f7 chore(main): release 4.5.0 (#1279)
🤖 I have created a release *beep* *boop*
---


## [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](e2d00dc346))
* api plugin system & offline versioned dependency vendoring
([#1252](https://github.com/unraid/api/issues/1252))
([9f492bf](9f492bf217))
* **api:** add `unraid-api --delete` command
([#1289](https://github.com/unraid/api/issues/1289))
([2f09445](2f09445f2e))
* basic array controls
([#1291](https://github.com/unraid/api/issues/1291))
([61fe696](61fe6966ca))
* basic docker controls
([#1292](https://github.com/unraid/api/issues/1292))
([12eddf8](12eddf894e))
* copy to webgui repo script docs + wc build options
([#1285](https://github.com/unraid/api/issues/1285))
([e54f189](e54f189630))


### Bug Fixes

* additional url fixes
([4b2763c](4b2763c7f9))
* **api:** redirect benign pnpm postinstall warning to log file
([#1290](https://github.com/unraid/api/issues/1290))
([7fb7849](7fb78494cb))
* **deps:** update dependency chalk to v5
([#1296](https://github.com/unraid/api/issues/1296))
([6bed638](6bed63805f))
* **deps:** update dependency diff to v7
([#1297](https://github.com/unraid/api/issues/1297))
([3c6683c](3c6683c814))
* disable all config watchers
([#1306](https://github.com/unraid/api/issues/1306))
([5c1b435](5c1b4352cf))
* extract callbacks to library
([#1280](https://github.com/unraid/api/issues/1280))
([2266139](2266139742))
* OEM plugin issues ([#1288](https://github.com/unraid/api/issues/1288))
([d5a3d0d](d5a3d0dfac))
* replace files lost during pruning
([d0d2ff6](d0d2ff65ed))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-04-02 13:24:42 -04:00
Eli Bosley
65b7747c0e chore: remove flaky test 2025-04-02 13:16:17 -04:00
Eli Bosley
5c1b4352cf fix: disable all config watchers (#1306)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Updated CLI operations now use sequential stop and start actions for
service reloads and SSO user modifications, ensuring a more controlled
update process.
- Introduced a new `<uui-toaster>` component for notifications,
replacing the previous jGrowl notification system and enhancing user
experience.
- Added functionality for managing live updates based on window focus,
improving responsiveness during user interaction.

- **Refactor**
- Streamlined configuration updates by removing automatic monitoring,
resulting in a simpler update workflow.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-04-02 13:09:47 -04:00
Eli Bosley
9004313ff8 chore: lint to fix build 2025-04-02 12:23:20 -04:00
Eli Bosley
7a421ce4ec chore: fix dev console and allowed-headers 2025-04-02 11:28:21 -04:00
renovate[bot]
3c6683c814 fix(deps): update dependency diff to v7 (#1297)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [diff](https://redirect.github.com/kpdecker/jsdiff) | [`^5.1.0` ->
`^7.0.0`](https://renovatebot.com/diffs/npm/diff/5.2.0/7.0.0) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/diff/7.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/diff/7.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/diff/5.2.0/7.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/diff/5.2.0/7.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>kpdecker/jsdiff (diff)</summary>

###
[`v7.0.0`](https://redirect.github.com/kpdecker/jsdiff/blob/HEAD/release-notes.md#700)

[Compare
Source](https://redirect.github.com/kpdecker/jsdiff/compare/v6.0.0...7.0.0)

Just a single (breaking) bugfix, undoing a behaviour change introduced
accidentally in 6.0.0:

- [#&#8203;554](https://redirect.github.com/kpdecker/jsdiff/pull/554)
**`diffWords` treats numbers and underscores as word characters again.**
This behaviour was broken in v6.0.0.

###
[`v6.0.0`](https://redirect.github.com/kpdecker/jsdiff/blob/HEAD/release-notes.md#600)

[Compare
Source](https://redirect.github.com/kpdecker/jsdiff/compare/v5.2.0...v6.0.0)

This is a release containing many, *many* breaking changes. The
objective of this release was to carry out a mass fix, in one go, of all
the open bugs and design problems that required breaking changes to fix.
A substantial, but exhaustive, changelog is below.


[Commits](https://redirect.github.com/kpdecker/jsdiff/compare/v5.2.0...v6.0.0)

- [#&#8203;497](https://redirect.github.com/kpdecker/jsdiff/pull/497)
**`diffWords` behavior has been radically changed.** Previously, even
with `ignoreWhitespace: true`, runs of whitespace were tokens, which led
to unhelpful and unintuitive diffing behavior in typical texts.
Specifically, even when two texts contained overlapping passages,
`diffWords` would sometimes choose to delete all the words from the old
text and insert them anew in their new positions in order to avoid
having to delete or insert whitespace tokens. Whitespace sequences are
no longer tokens as of this release, which affects both the generated
diffs and the `count`s.

    Runs of whitespace are still tokens in `diffWordsWithSpace`.

As part of the changes to `diffWords`, **a new `.postProcess` method has
been added on the base `Diff` type**, which can be overridden in custom
`Diff` implementations.

**`diffLines` with `ignoreWhitespace: true` will no longer ignore the
insertion or deletion of entire extra lines of whitespace at the end of
the text**. Previously, these would not show up as insertions or
deletions, as a side effect of a hack in the base diffing algorithm
meant to help ignore whitespace in `diffWords`. More generally, **the
undocumented special handling in the core algorithm for ignored
terminals has been removed entirely.** (This special case behavior used
to rewrite the final two change objects in a scenario where the final
change object was an addition or deletion and its `value` was treated as
equal to the empty string when compared using the diff object's
`.equals` method.)

- [#&#8203;500](https://redirect.github.com/kpdecker/jsdiff/pull/500)
**`diffChars` now diffs Unicode code points** instead of UTF-16 code
units.

- [#&#8203;508](https://redirect.github.com/kpdecker/jsdiff/pull/508)
**`parsePatch` now always runs in what was previously "strict" mode; the
undocumented `strict` option has been removed.** Previously, by default,
`parsePatch` (and other patch functions that use it under the hood to
parse patches) would accept a patch where the line counts in the headers
were inconsistent with the actual patch content - e.g. where a hunk
started with the header `@@&#8203; -1,3 +1,6 @&#8203;@&#8203;`,
indicating that the content below spanned 3 lines in the old file and 6
lines in the new file, but then the actual content below the header
consisted of some different number of lines, say 10 lines of context, 5
deletions, and 1 insertion. Actually trying to work with these patches
using `applyPatch` or `merge`, however, would produce incorrect results
instead of just ignoring the incorrect headers, making this "feature"
more of a trap than something actually useful. It's been ripped out, and
now we are always "strict" and will reject patches where the line counts
in the headers aren't consistent with the actual patch content.

- [#&#8203;435](https://redirect.github.com/kpdecker/jsdiff/pull/435)
**Fix `parsePatch` handling of control characters.** `parsePatch` used
to interpret various unusual control characters - namely vertical tabs,
form feeds, lone carriage returns without a line feed, and EBCDIC NELs -
as line breaks when parsing a patch file. This was inconsistent with the
behavior of both JsDiff's own `diffLines` method and also the Unix
`diff` and `patch` utils, which all simply treat those control
characters as ordinary characters. The result of this discrepancy was
that some well-formed patches - produced either by `diff` or by JsDiff
itself and handled properly by the `patch` util - would be wrongly
parsed by `parsePatch`, with the effect that it would disregard the
remainder of a hunk after encountering one of these control characters.

- [#&#8203;439](https://redirect.github.com/kpdecker/jsdiff/pull/439)
**Prefer diffs that order deletions before insertions.** When faced with
a choice between two diffs with an equal total edit distance, the Myers
diff algorithm generally prefers one that does deletions before
insertions rather than insertions before deletions. For instance, when
diffing `abcd` against `acbd`, it will prefer a diff that says to delete
the `b` and then insert a new `b` after the `c`, over a diff that says
to insert a `c` before the `b` and then delete the existing `c`. JsDiff
deviated from the published Myers algorithm in a way that led to it
having the opposite preference in many cases, including that example.
This is now fixed, meaning diffs output by JsDiff will more accurately
reflect what the published Myers diff algorithm would output.

- [#&#8203;455](https://redirect.github.com/kpdecker/jsdiff/pull/455)
**The `added` and `removed` properties of change objects are now
guaranteed to be set to a boolean value.** (Previously, they would be
set to `undefined` or omitted entirely instead of setting them to
false.)

- [#&#8203;464](https://redirect.github.com/kpdecker/jsdiff/pull/464)
Specifying `{maxEditLength: 0}` now sets a max edit length of 0 instead
of no maximum.

- [#&#8203;460](https://redirect.github.com/kpdecker/jsdiff/pull/460)
**Added `oneChangePerToken` option.**

- [#&#8203;467](https://redirect.github.com/kpdecker/jsdiff/pull/467)
**Consistent ordering of arguments to `comparator(left, right)`.**
Values from the old array will now consistently be passed as the first
argument (`left`) and values from the new array as the second argument
(`right`). Previously this was almost (but not quite) always the other
way round.

- [#&#8203;480](https://redirect.github.com/kpdecker/jsdiff/pull/480)
**Passing `maxEditLength` to `createPatch` & `createTwoFilesPatch` now
works properly** (i.e. returns undefined if the max edit distance is
exceeded; previous behavior was to crash with a `TypeError` if the edit
distance was exceeded).

- [#&#8203;486](https://redirect.github.com/kpdecker/jsdiff/pull/486)
**The `ignoreWhitespace` option of `diffLines` behaves more sensibly
now.** `value`s in returned change objects now include leading/trailing
whitespace even when `ignoreWhitespace` is used, just like how with
`ignoreCase` the `value`s still reflect the case of one of the original
texts instead of being all-lowercase. `ignoreWhitespace` is also now
compatible with `newlineIsToken`. Finally, **`diffTrimmedLines` is
deprecated** (and removed from the docs) in favour of using `diffLines`
with `ignoreWhitespace: true`; the two are, and always have been,
equivalent.

- [#&#8203;490](https://redirect.github.com/kpdecker/jsdiff/pull/490)
**When calling diffing functions in async mode by passing a `callback`
option, the diff result will now be passed as the *first* argument to
the callback instead of the second.** (Previously, the first argument
was never used at all and would always have value `undefined`.)

- [#&#8203;489](redirect.github.com/kpdecker/jsdiff/pull/489)
**`this.options` no longer exists on `Diff` objects.** Instead,
`options` is now passed as an argument to methods that rely on options,
like `equals(left, right, options)`. This fixes a race condition in
async mode, where diffing behaviour could be changed mid-execution if a
concurrent usage of the same `Diff` instances overwrote its `options`.

- [#&#8203;518](https://redirect.github.com/kpdecker/jsdiff/pull/518)
**`linedelimiters` no longer exists** on patch objects; instead, when a
patch with Windows-style CRLF line endings is parsed, **the lines in
`lines` will end with `\r`**. There is now a **new
`autoConvertLineEndings` option, on by default**, which makes it so that
when a patch with Windows-style line endings is applied to a source file
with Unix style line endings, the patch gets autoconverted to use
Unix-style line endings, and when a patch with Unix-style line endings
is applied to a source file with Windows-style line endings, it gets
autoconverted to use Windows-style line endings.

- [#&#8203;521](https://redirect.github.com/kpdecker/jsdiff/pull/521)
**the `callback` option is now supported by `structuredPatch`,
`createPatch`, and `createTwoFilesPatch`**

- [#&#8203;529](https://redirect.github.com/kpdecker/jsdiff/pull/529)
**`parsePatch` can now parse patches where lines starting with `--` or
`++` are deleted/inserted**; previously, there were edge cases where the
parser would choke on valid patches or give wrong results.

- [#&#8203;530](https://redirect.github.com/kpdecker/jsdiff/pull/530)
**Added `ignoreNewlineAtEof` option to `diffLines`**

- [#&#8203;533](https://redirect.github.com/kpdecker/jsdiff/pull/533)
**`applyPatch` uses an entirely new algorithm for fuzzy matching.**
Differences between the old and new algorithm are as follows:
- The `fuzzFactor` now indicates the maximum [*Levenshtein*
distance](https://en.wikipedia.org/wiki/Levenshtein_distance) that there
can be between the context shown in a hunk and the actual file content
at a location where we try to apply the hunk. (Previously, it
represented a maximum [*Hamming*
distance](https://en.wikipedia.org/wiki/Hamming_distance), meaning that
a single insertion or deletion in the source file could stop a hunk from
applying even with a high `fuzzFactor`.)
- A hunk containing a deletion can now only be applied in a context
where the line to be deleted actually appears verbatim. (Previously, as
long as enough context lines in the hunk matched, `applyPatch` would
apply the hunk anyway and delete a completely different line.)
- The context line immediately before and immediately after an insertion
must match exactly between the hunk and the file for a hunk to apply.
(Previously this was not required.)

- [#&#8203;535](https://redirect.github.com/kpdecker/jsdiff/pull/535)
**A bug in patch generation functions is now fixed** that would
sometimes previously cause `\ No newline at end of file` to appear in
the wrong place in the generated patch, resulting in the patch being
invalid. **These invalid patches can also no longer be applied
successfully with `applyPatch`.** (It was already the case that tools
other than jsdiff, like GNU `patch`, would consider them malformed and
refuse to apply them; versions of jsdiff with this fix now do the same
thing if you ask them to apply a malformed patch emitted by jsdiff v5.)

- [#&#8203;535](https://redirect.github.com/kpdecker/jsdiff/pull/535)
**Passing `newlineIsToken: true` to *patch*-generation functions is no
longer allowed.** (Passing it to `diffLines` is still supported - it's
only functions like `createPatch` where passing `newlineIsToken` is now
an error.) Allowing it to be passed never really made sense, since in
cases where the option had any effect on the output at all, the effect
tended to be causing a garbled patch to be created that couldn't
actually be applied to the source file.

- [#&#8203;539](https://redirect.github.com/kpdecker/jsdiff/pull/539)
**`diffWords` now takes an optional `intlSegmenter` option** which
should be an `Intl.Segmenter` with word-level granularity. This provides
better tokenization of text into words than the default behaviour, even
for English but especially for some other languages for which the
default behaviour is poor.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [x] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-02 09:42:46 -04:00
renovate[bot]
6bed63805f fix(deps): update dependency chalk to v5 (#1296)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [chalk](https://redirect.github.com/chalk/chalk) | [`^4.1.2` ->
`^5.0.0`](https://renovatebot.com/diffs/npm/chalk/4.1.2/5.4.1) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/chalk/5.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/chalk/5.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/chalk/4.1.2/5.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/chalk/4.1.2/5.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>chalk/chalk (chalk)</summary>

###
[`v5.4.1`](https://redirect.github.com/chalk/chalk/releases/tag/v5.4.1)

[Compare
Source](https://redirect.github.com/chalk/chalk/compare/v5.4.0...v5.4.1)

- Fix `navigator` not defined `ReferenceError`
([#&#8203;642](https://redirect.github.com/chalk/chalk/issues/642))
[`4ebb62d`](https://redirect.github.com/chalk/chalk/commit/4ebb62d)

###
[`v5.4.0`](https://redirect.github.com/chalk/chalk/releases/tag/v5.4.0)

[Compare
Source](https://redirect.github.com/chalk/chalk/compare/v5.3.0...v5.4.0)

- Update `CIRCLECI` environments to return level 3 color support
[`f838120`](https://redirect.github.com/chalk/chalk/commit/f838120)

###
[`v5.3.0`](https://redirect.github.com/chalk/chalk/releases/tag/v5.3.0)

[Compare
Source](https://redirect.github.com/chalk/chalk/compare/v5.2.0...v5.3.0)

- Add `sideEffects` field to package.json
[`5aafc0a`](https://redirect.github.com/chalk/chalk/commit/5aafc0a)
- Add support for Gitea Actions
([#&#8203;603](https://redirect.github.com/chalk/chalk/issues/603))
[`29b8569`](https://redirect.github.com/chalk/chalk/commit/29b8569)

###
[`v5.2.0`](https://redirect.github.com/chalk/chalk/releases/tag/v5.2.0)

[Compare
Source](https://redirect.github.com/chalk/chalk/compare/v5.1.2...v5.2.0)

- Improve Deno compatibility
([#&#8203;579](https://redirect.github.com/chalk/chalk/issues/579))
[`7443e9f`](https://redirect.github.com/chalk/chalk/commit/7443e9f)
- Detect true-color support for GitHub Actions
([#&#8203;579](https://redirect.github.com/chalk/chalk/issues/579))
[`7443e9f`](https://redirect.github.com/chalk/chalk/commit/7443e9f)
- Detect true-color support for Kitty terminal
([#&#8203;579](https://redirect.github.com/chalk/chalk/issues/579))
[`7443e9f`](https://redirect.github.com/chalk/chalk/commit/7443e9f)
- Fix test for Azure DevOps environment
([#&#8203;579](https://redirect.github.com/chalk/chalk/issues/579))
[`7443e9f`](https://redirect.github.com/chalk/chalk/commit/7443e9f)

###
[`v5.1.2`](https://redirect.github.com/chalk/chalk/releases/tag/v5.1.2)

[Compare
Source](https://redirect.github.com/chalk/chalk/compare/v5.1.1...v5.1.2)

- Fix exported styles names
([#&#8203;569](https://redirect.github.com/chalk/chalk/issues/569))
[`a34bcf6`](https://redirect.github.com/chalk/chalk/commit/a34bcf6)

###
[`v5.1.1`](https://redirect.github.com/chalk/chalk/releases/tag/v5.1.1)

[Compare
Source](https://redirect.github.com/chalk/chalk/compare/v5.1.0...v5.1.1)

- Improved the names of exports introduced in 5.1.0
([#&#8203;567](https://redirect.github.com/chalk/chalk/issues/567))
[`6e0df05`](https://redirect.github.com/chalk/chalk/commit/6e0df05)
    -   We of course preserved the old names.

###
[`v5.1.0`](https://redirect.github.com/chalk/chalk/releases/tag/v5.1.0)

[Compare
Source](https://redirect.github.com/chalk/chalk/compare/v5.0.1...v5.1.0)

- Expose style names
([#&#8203;566](https://redirect.github.com/chalk/chalk/issues/566))
[`d7d7571`](https://redirect.github.com/chalk/chalk/commit/d7d7571)

###
[`v5.0.1`](https://redirect.github.com/chalk/chalk/releases/tag/v5.0.1)

[Compare
Source](https://redirect.github.com/chalk/chalk/compare/v5.0.0...v5.0.1)

- Add `main` field to package.json for backwards compatibility with some
developer tools
[`85f7e96`](https://redirect.github.com/chalk/chalk/commit/85f7e96)

###
[`v5.0.0`](https://redirect.github.com/chalk/chalk/releases/tag/v5.0.0)

[Compare
Source](https://redirect.github.com/chalk/chalk/compare/v4.1.2...v5.0.0)

##### Breaking

- **This package is now pure ESM. Please [read
this](https://gist.github.com/sindresorhus/a39789f98801d908bbc7ff3ecc99d99c).**
- If you use TypeScript, you need to use TypeScript 4.7 or later.
[Why.](https://redirect.github.com/microsoft/TypeScript/issues/46452)
- If you use a bundler, make sure it supports ESM and that you have
correctly configured it for ESM.
- The Chalk issue tracker is not a support channel for your favorite
build/bundler tool.
- It's totally fine to stay on Chalk v4. It's been stable for years.
- Require Node.js 12.20
[`fa16f4e`](https://redirect.github.com/chalk/chalk/commit/fa16f4e)
- Move some properties off the default export to individual named
exports:
    -   `chalk.Instance` → `Chalk`
    -   `chalk.supportsColor` → `supportsColor`
    -   `chalk.stderr` → `chalkStderr`
    -   `chalk.stderr.supportsColor` → `supportsColorStderr`
- Remove `.keyword()`, `.hsl()`, `.hsv()`, `.hwb()`, and `.ansi()`
coloring methods
([#&#8203;433](https://redirect.github.com/chalk/chalk/issues/433))
[`4cf2e40`](https://redirect.github.com/chalk/chalk/commit/4cf2e40)
- These were not commonly used and added a lot of bloat to Chalk. You
can achieve the same by using the [`color-convert`
package](https://redirect.github.com/Qix-/color-convert).
- The tagged template literal support moved into a separate package:
[`chalk-template`](https://redirect.github.com/chalk/chalk-template)
([#&#8203;524](https://redirect.github.com/chalk/chalk/issues/524))
[`c987c61`](https://redirect.github.com/chalk/chalk/commit/c987c61)

```diff
-import chalk from 'chalk';
+import chalkTemplate from 'chalk-template';

-chalk`2 + 3 = {bold ${2 + 3}}`;
+chalkTemplate`2 + 3 = {bold ${2 + 3}}`;
```

##### Improvements

- Bundle dependencies
[`04fdbd6`](https://redirect.github.com/chalk/chalk/commit/04fdbd6)
    -   This means Chalk no longer has any dependencies 🎉
- [The install size is less than half of
v4.](https://packagephobia.com/result?p=chalk)
- Add `overline` style
([#&#8203;433](https://redirect.github.com/chalk/chalk/issues/433))
[`4cf2e40`](https://redirect.github.com/chalk/chalk/commit/4cf2e40)
- Preserve function prototype methods
([#&#8203;434](https://redirect.github.com/chalk/chalk/issues/434))
[`0fba91b`](https://redirect.github.com/chalk/chalk/commit/0fba91b)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-02 09:40:22 -04:00
renovate[bot]
f7f40d7906 fix(deps): update all non-major dependencies (#1278)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@graphql-codegen/typescript-resolvers](https://redirect.github.com/dotansimha/graphql-code-generator)
([source](https://redirect.github.com/dotansimha/graphql-code-generator/tree/HEAD/packages/plugins/typescript/resolvers))
| [`4.4.4` ->
`4.5.0`](https://renovatebot.com/diffs/npm/@graphql-codegen%2ftypescript-resolvers/4.4.4/4.5.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@graphql-codegen%2ftypescript-resolvers/4.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@graphql-codegen%2ftypescript-resolvers/4.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@graphql-codegen%2ftypescript-resolvers/4.4.4/4.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@graphql-codegen%2ftypescript-resolvers/4.4.4/4.5.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [lucide-vue-next](https://lucide.dev)
([source](https://redirect.github.com/lucide-icons/lucide/tree/HEAD/packages/lucide-vue-next))
| [`^0.483.0` ->
`^0.487.0`](https://renovatebot.com/diffs/npm/lucide-vue-next/0.483.0/0.487.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/lucide-vue-next/0.487.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/lucide-vue-next/0.487.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/lucide-vue-next/0.483.0/0.487.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/lucide-vue-next/0.483.0/0.487.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [pnpm](https://pnpm.io)
([source](https://redirect.github.com/pnpm/pnpm/tree/HEAD/pnpm)) |
[`10.6.5` ->
`10.7.1`](https://renovatebot.com/diffs/npm/pnpm/10.6.5/10.7.1) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/pnpm/10.7.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/pnpm/10.7.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/pnpm/10.6.5/10.7.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/pnpm/10.6.5/10.7.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[vuetify-nuxt-module](https://redirect.github.com/vuetifyjs/nuxt-module)
| [`0.18.4` ->
`0.18.5`](https://renovatebot.com/diffs/npm/vuetify-nuxt-module/0.18.4/0.18.5)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/vuetify-nuxt-module/0.18.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vuetify-nuxt-module/0.18.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vuetify-nuxt-module/0.18.4/0.18.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vuetify-nuxt-module/0.18.4/0.18.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>dotansimha/graphql-code-generator
(@&#8203;graphql-codegen/typescript-resolvers)</summary>

###
[`v4.5.0`](https://redirect.github.com/dotansimha/graphql-code-generator/blob/HEAD/packages/plugins/typescript/resolvers/CHANGELOG.md#450)

[Compare
Source](https://redirect.github.com/dotansimha/graphql-code-generator/compare/@graphql-codegen/typescript-resolvers@4.4.4...@graphql-codegen/typescript-resolvers@4.5.0)

##### Minor Changes

-
[#&#8203;10315](https://redirect.github.com/dotansimha/graphql-code-generator/pull/10315)
[`f6909d1`](f6909d1797)
Thanks [@&#8203;eddeee888](https://redirect.github.com/eddeee888)! -
Implement semanticNonNull custom directive

##### Patch Changes

- Updated dependencies
\[[`f6909d1`](f6909d1797)]:
-
[@&#8203;graphql-codegen/visitor-plugin-common](https://redirect.github.com/graphql-codegen/visitor-plugin-common)[@&#8203;5](https://redirect.github.com/5).8.0
-
[@&#8203;graphql-codegen/typescript](https://redirect.github.com/graphql-codegen/typescript)[@&#8203;4](https://redirect.github.com/4).1.6

</details>

<details>
<summary>lucide-icons/lucide (lucide-vue-next)</summary>

###
[`v0.487.0`](https://redirect.github.com/lucide-icons/lucide/releases/tag/0.487.0):
Version 0.487.0

[Compare
Source](https://redirect.github.com/lucide-icons/lucide/compare/0.486.0...0.487.0)

#### What's Changed

- feat(icons): added `spline-pointer` icon by
[@&#8203;Kaleidosium](https://redirect.github.com/Kaleidosium) in
[https://github.com/lucide-icons/lucide/pull/2932](https://redirect.github.com/lucide-icons/lucide/pull/2932)

#### New Contributors

- [@&#8203;Kaleidosium](https://redirect.github.com/Kaleidosium) made
their first contribution in
[https://github.com/lucide-icons/lucide/pull/2932](https://redirect.github.com/lucide-icons/lucide/pull/2932)

**Full Changelog**:
https://github.com/lucide-icons/lucide/compare/0.486.0...0.487.0

###
[`v0.486.0`](https://redirect.github.com/lucide-icons/lucide/releases/tag/0.486.0):
Version 0.486.0

[Compare
Source](https://redirect.github.com/lucide-icons/lucide/compare/0.485.0...0.486.0)

#### What's Changed

-
feat([@&#8203;lucide/astro](https://redirect.github.com/lucide/astro)):
add lucide package for Astro by
[@&#8203;MoustaphaDev](https://redirect.github.com/MoustaphaDev) in
[https://github.com/lucide-icons/lucide/pull/2665](https://redirect.github.com/lucide-icons/lucide/pull/2665)

#### New Contributors

- [@&#8203;MoustaphaDev](https://redirect.github.com/MoustaphaDev) made
their first contribution in
[https://github.com/lucide-icons/lucide/pull/2665](https://redirect.github.com/lucide-icons/lucide/pull/2665)

**Full Changelog**:
https://github.com/lucide-icons/lucide/compare/0.485.0...0.486.0

###
[`v0.485.0`](https://redirect.github.com/lucide-icons/lucide/releases/tag/0.485.0):
Version 0.485.0

[Compare
Source](https://redirect.github.com/lucide-icons/lucide/compare/0.484.0...0.485.0)

#### What's Changed

- feat(icons): added `banknote-arrow-down` icon by
[@&#8203;joffx](https://redirect.github.com/joffx) in
[https://github.com/lucide-icons/lucide/pull/2948](https://redirect.github.com/lucide-icons/lucide/pull/2948)
- feat(icons): added `banknote-x` icon by
[@&#8203;joffx](https://redirect.github.com/joffx) in
[https://github.com/lucide-icons/lucide/pull/2949](https://redirect.github.com/lucide-icons/lucide/pull/2949)

**Full Changelog**:
https://github.com/lucide-icons/lucide/compare/0.484.0...0.485.0

###
[`v0.484.0`](https://redirect.github.com/lucide-icons/lucide/releases/tag/0.484.0):
Version 0.484.0

[Compare
Source](https://redirect.github.com/lucide-icons/lucide/compare/0.483.0...0.484.0)

#### What's Changed

- build(deps): bump tj-actions/changed-files from 41 to 46 in
/.github/workflows by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/lucide-icons/lucide/pull/2920](https://redirect.github.com/lucide-icons/lucide/pull/2920)
- fix(packages): consistent icon name class by
[@&#8203;danteissaias](https://redirect.github.com/danteissaias) in
[https://github.com/lucide-icons/lucide/pull/2878](https://redirect.github.com/lucide-icons/lucide/pull/2878)
- feat(ci): add `x.com` to brand filter by
[@&#8203;jguddas](https://redirect.github.com/jguddas) in
[https://github.com/lucide-icons/lucide/pull/2939](https://redirect.github.com/lucide-icons/lucide/pull/2939)
- fix(icons): arcified candy & candy-off by
[@&#8203;karsa-mistmere](https://redirect.github.com/karsa-mistmere) in
[https://github.com/lucide-icons/lucide/pull/2944](https://redirect.github.com/lucide-icons/lucide/pull/2944)

#### New Contributors

- [@&#8203;danteissaias](https://redirect.github.com/danteissaias) made
their first contribution in
[https://github.com/lucide-icons/lucide/pull/2878](https://redirect.github.com/lucide-icons/lucide/pull/2878)

**Full Changelog**:
https://github.com/lucide-icons/lucide/compare/0.483.0...0.484.0

</details>

<details>
<summary>pnpm/pnpm (pnpm)</summary>

###
[`v10.7.1`](https://redirect.github.com/pnpm/pnpm/releases/tag/v10.7.1):
pnpm 10.7.1

[Compare
Source](https://redirect.github.com/pnpm/pnpm/compare/v10.7.0...v10.7.1)

#### Patch Changes

- `pnpm config set` should convert the settings to their correct type
before adding them to `pnpm-workspace.yaml`
[#&#8203;9355](https://redirect.github.com/pnpm/pnpm/issues/9355).
- `pnpm config get` should read auth related settings via npm CLI
[#&#8203;9345](https://redirect.github.com/pnpm/pnpm/issues/9345).
- Replace leading `~/` in a path in `.npmrc` with the home directory
[#&#8203;9217](https://redirect.github.com/pnpm/pnpm/issues/9217).

#### Platinum Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
<a href="https://bit.dev/?utm_source=pnpm&utm_medium=release_notes"
target="_blank"><img src="https://pnpm.io/img/users/bit.svg" width="80"
alt="Bit"></a>
      </td>
      <td align="center" valign="middle">
<a href="https://sanity.io/?utm_source=pnpm&utm_medium=release_notes"
target="_blank"><img src="https://pnpm.io/img/users/sanity.svg"
width="180" alt="Bit"></a>
      </td>
      <td align="center" valign="middle">
<a href="https://syntax.fm/?utm_source=pnpm&utm_medium=release_notes"
target="_blank">
          <picture>
<source media="(prefers-color-scheme: light)"
srcset="https://pnpm.io/img/users/syntaxfm.svg" />
<source media="(prefers-color-scheme: dark)"
srcset="https://pnpm.io/img/users/syntaxfm_light.svg" />
<img src="https://pnpm.io/img/users/syntaxfm.svg" width="90"
alt="Syntax" />
          </picture>
        </a>
      </td>
    </tr>
  </tbody>
</table>

#### Gold Sponsors

<table>
  <tbody>
    <tr>
      <td align="center" valign="middle">
<a href="https://discord.com/?utm_source=pnpm&utm_medium=release_notes"
target="_blank">
          <picture>
<source media="(prefers-color-scheme: light)"
srcset="https://pnpm.io/img/users/discord.svg" />
<source media="(prefers-color-scheme: dark)"
srcset="https://pnpm.io/img/users/discord_light.svg" />
<img src="https://pnpm.io/img/users/discord.svg" width="220"
alt="Discord" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
<a href="https://uscreen.de/?utm_source=pnpm&utm_medium=release_notes"
target="_blank">
          <picture>
<source media="(prefers-color-scheme: light)"
srcset="https://pnpm.io/img/users/uscreen.svg" />
<source media="(prefers-color-scheme: dark)"
srcset="https://pnpm.io/img/users/uscreen_light.svg" />
<img src="https://pnpm.io/img/users/uscreen.svg" width="180"
alt="u|screen" />
          </picture>
        </a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
<a
href="https://www.jetbrains.com/?utm_source=pnpm&utm_medium=release_notes"
target="_blank">
          <picture>
<source media="(prefers-color-scheme: light)"
srcset="https://pnpm.io/img/users/jetbrains.svg" />
<source media="(prefers-color-scheme: dark)"
srcset="https://pnpm.io/img/users/jetbrains.svg" />
<img src="https://pnpm.io/img/users/jetbrains.svg" width="180"
alt="JetBrains" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
<a href="https://nx.dev/?utm_source=pnpm&utm_medium=release_notes"
target="_blank">
          <picture>
<source media="(prefers-color-scheme: light)"
srcset="https://pnpm.io/img/users/nx.svg?0" />
<source media="(prefers-color-scheme: dark)"
srcset="https://pnpm.io/img/users/nx_light.svg?0" />
<img src="https://pnpm.io/img/users/nx.svg" width="70" alt="Nx" />
          </picture>
        </a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
<a
href="https://coderabbit.ai/?utm_source=pnpm&utm_medium=release_notes"
target="_blank">
          <picture>
<source media="(prefers-color-scheme: light)"
srcset="https://pnpm.io/img/users/coderabbit.svg" />
<source media="(prefers-color-scheme: dark)"
srcset="https://pnpm.io/img/users/coderabbit_light.svg" />
<img src="https://pnpm.io/img/users/coderabbit.svg" width="220"
alt="CodeRabbit" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
<a href="https://route4me.com/?utm_source=pnpm&utm_medium=release_notes"
target="_blank">
<img src="https://pnpm.io/img/users/route4me.svg" width="220"
alt="Route4Me" />
        </a>
      </td>
    </tr>
    <tr>
      <td align="center" valign="middle">
<a href="https://workleap.com/?utm_source=pnpm&utm_medium=release_notes"
target="_blank">
          <picture>
<source media="(prefers-color-scheme: light)"
srcset="https://pnpm.io/img/users/workleap.svg" />
<source media="(prefers-color-scheme: dark)"
srcset="https://pnpm.io/img/users/workleap_light.svg" />
<img src="https://pnpm.io/img/users/workleap.svg" width="190"
alt="Workleap" />
          </picture>
        </a>
      </td>
      <td align="center" valign="middle">
<a
href="https://stackblitz.com/?utm_source=pnpm&utm_medium=release_notes"
target="_blank">
          <picture>
<source media="(prefers-color-scheme: light)"
srcset="https://pnpm.io/img/users/stackblitz.svg" />
<source media="(prefers-color-scheme: dark)"
srcset="https://pnpm.io/img/users/stackblitz_light.svg" />
<img src="https://pnpm.io/img/users/stackblitz.svg" width="190"
alt="Stackblitz" />
          </picture>
        </a>
      </td>
    </tr>
  </tbody>
</table>

###
[`v10.7.0`](https://redirect.github.com/pnpm/pnpm/blob/HEAD/pnpm/CHANGELOG.md#1070)

[Compare
Source](https://redirect.github.com/pnpm/pnpm/compare/v10.6.5...v10.7.0)

##### Minor Changes

- `pnpm config get` and `list` also show settings set in
`pnpm-workspace.yaml` files
[#&#8203;9316](https://redirect.github.com/pnpm/pnpm/pull/9316).

- It should be possible to use env variables in `pnpm-workspace.yaml`
setting names and value.

- Add an ability to patch dependencies by version ranges. Exact versions
override version ranges, which in turn override name-only patches.
Version range `*` is the same as name-only, except that patch
application failure will not be ignored.

    For example:

    ```yaml
    patchedDependencies:
      foo: patches/foo-1.patch
      foo@^2.0.0: patches/foo-2.patch
      foo@2.1.0: patches/foo-3.patch
    ```

The above configuration would apply `patches/foo-3.patch` to
`foo@2.1.0`, `patches/foo-2.patch` to all `foo` versions which satisfy
`^2.0.0` except `2.1.0`, and `patches/foo-1.patch` to the remaining
`foo` versions.

    > \[!WARNING]
> The version ranges should not overlap. If you want to specialize a sub
range, make sure to exclude it from the other keys. For example:
    >
    > ```yaml
    > # pnpm-workspace.yaml
    > patchedDependencies:
    >   # the specialized sub range
    >   'foo@2.2.0-2.8.0': patches/foo.2.2.0-2.8.0.patch
    >   # the more general patch, excluding the sub range above
    >   'foo@>=2.0.0 <2.2.0 || >2.8.0': 'patches/foo.gte2.patch
    > ```
    >
> In most cases, however, it's sufficient to just define an exact
version to override the range.

- `pnpm config set --location=project` saves the setting to a
`pnpm-workspace.yaml` file if no `.npmrc` file is present in the
directory
[#&#8203;9316](https://redirect.github.com/pnpm/pnpm/pull/9316).

- Rename `pnpm.allowNonAppliedPatches` to `pnpm.allowUnusedPatches`. The
old name is still supported but it would print a deprecation warning
message.

- Add `pnpm.ignorePatchFailures` to manage whether pnpm would ignore
patch application failures.

If `ignorePatchFailures` is not set, pnpm would throw an error when
patches with exact versions or version ranges fail to apply, and it
would ignore failures from name-only patches.

If `ignorePatchFailures` is explicitly set to `false`, pnpm would throw
an error when any type of patch fails to apply.

If `ignorePatchFailures` is explicitly set to `true`, pnpm would print a
warning when any type of patch fails to apply.

##### Patch Changes

- Remove dependency paths from audit output to prevent out-of-memory
errors
[#&#8203;9280](https://redirect.github.com/pnpm/pnpm/issues/9280).

</details>

<details>
<summary>vuetifyjs/nuxt-module (vuetify-nuxt-module)</summary>

###
[`v0.18.5`](https://redirect.github.com/vuetifyjs/nuxt-module/releases/tag/v0.18.5)

[Compare
Source](https://redirect.github.com/vuetifyjs/nuxt-module/compare/v0.18.4...v0.18.5)

#####    🐞 Bug Fixes

- **styles**: Resolve new scss component styles  -  by
[@&#8203;userquin](https://redirect.github.com/userquin) in
[https://github.com/vuetifyjs/nuxt-module/issues/305](https://redirect.github.com/vuetifyjs/nuxt-module/issues/305)
[<samp>(82139)</samp>](https://redirect.github.com/vuetifyjs/nuxt-module/commit/8213962)

#####     [View changes on
GitHub](https://redirect.github.com/vuetifyjs/nuxt-module/compare/v0.18.4...v0.18.5)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIyNy4zIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-04-02 09:40:11 -04:00
Zack Spear
e2d00dc346 feat: add webgui theme switcher component (#1304)
For now just used in Dev Mode to help assist in testing webgui CSS
changes.

- Introduced a new `UnraidThemeSwitcher` component to allow users to
change themes dynamically.
- Updated `nuxt.config.ts` to register the new component.
- Created `ThemeSwitcher.ce.vue` with functionality to handle theme
changes and update the UI accordingly.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Introduced a theme switcher, allowing users to easily swap between
available application themes.
- Expanded the configuration to register the new theme switcher as a
custom element for seamless integration.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-04-01 14:13:42 -07:00
Pujit Mehrotra
48c6ad7afa chore: fix license badge & add community links (#1300)
shields.io couldn't "recognize" our license.md, so it's statically
generated now.

## Summary by CodeRabbit

- **Documentation**
- Revised the project description and updated the documentation URL for
clearer API guidance.
  - Enhanced visual presentation by centering project shields.
  - Added a new badge to highlight the use of Vite.
- Restructured contact information into a new "Community" section with
updated channels.
  - Updated licensing details to reflect the GPL-2.0 license.
2025-03-31 16:22:26 -04:00
Eli Bosley
12eddf894e feat: basic docker controls (#1292)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Chores**
- Updated configuration settings by resetting various parameters to
default values.
	- Enhanced module integration with new Docker components.
- **New Features**
	- Introduced GraphQL API endpoints to start and stop Docker containers.
	- Added a backend service to manage Docker container operations.
- **Tests**
- Expanded test suites covering Docker resolvers and service methods to
ensure reliable container management.
- **Refactor**
- Consolidated code imports and streamlined internal calls for clearer
structure.
	- Enhanced type safety for Docker container retrieval parameters.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-03-31 16:21:06 -04:00
Eli Bosley
61fe6966ca feat: basic array controls (#1291)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Expanded API operations for array management, including new mutations
for state changes and disk handling.
- Introduced new enumeration and input types for managing array states
in the GraphQL schema.
- Added a new resolver for handling array mutations in the GraphQL API.

- **Chores**
- Upgraded configuration version to 4.4.1 and refined connectivity
status reporting.

- **Refactor**
- Streamlined request processing with improved error handling to provide
clearer feedback on connectivity issues.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-03-31 15:47:33 -04:00
renovate[bot]
b4c8efa483 fix(deps): update dependency ignore to v7 (#1299)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [ignore](https://redirect.github.com/kaelzhang/node-ignore) |
[`^5.2.4` ->
`^7.0.0`](https://renovatebot.com/diffs/npm/ignore/5.3.2/7.0.3) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/ignore/7.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/ignore/7.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/ignore/5.3.2/7.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/ignore/5.3.2/7.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>kaelzhang/node-ignore (ignore)</summary>

###
[`v7.0.3`](52f8e855b6...7.0.3)

[Compare
Source](52f8e855b6...7.0.3)

###
[`v7.0.2`](https://redirect.github.com/kaelzhang/node-ignore/compare/7.0.1...52f8e855b6aca711579c008f38829f48e5a4c78b)

[Compare
Source](https://redirect.github.com/kaelzhang/node-ignore/compare/7.0.1...52f8e855b6aca711579c008f38829f48e5a4c78b)

###
[`v7.0.1`](https://redirect.github.com/kaelzhang/node-ignore/compare/7.0.0...7.0.1)

[Compare
Source](https://redirect.github.com/kaelzhang/node-ignore/compare/7.0.0...7.0.1)

###
[`v7.0.0`](https://redirect.github.com/kaelzhang/node-ignore/releases/tag/7.0.0)

[Compare
Source](ee70c66d32...7.0.0)

#### Minor feature

The primary feature introduced by `7.0.0` is the `.checkIgnore()`
method, which is most equivalent to `git check-ignore -v`. And also it
allows to pass `{pattern, mark?}` as the parameter of `.add()` so that
we could imitate the mechanism of `git check-ignore` as:

```js
ig.add({
  pattern: 'foo/*',
  mark: '60'
})

const {
  ignored,
  rule
} = checkIgnore('foo/')

if (ignored) {
  console.log(`.gitignore:${result}:${rule.mark}:${rule.pattern} foo/`)
}

// .gitignore:60:foo/* foo/
```

#### Potential Incompatibilities

The only situation that `7.0.0` might bring incompatibility is to
`.add()` a `< 7.0.0` instance into a `>= 7.0.0` instance, which might
occur when the current workspace has multiple `node-ignore` versions
installed, please be careful.

```js
const {anotherIgnoreInstance} = require('./ignore-6.0-instance')

// A 7.0.0 instance
ignore().add(anotherIgnoreInstance)

// It will break your code
```

Otherwise, in most cases, if you never do something above or there is
only one version of `node-ignore` installed in the current workspace, it
is quite safe to upgrade to `7.0.0`.

###
[`v6.0.2`](https://redirect.github.com/kaelzhang/node-ignore/compare/6.0.1...ee70c66d32e900f6e793c733a4ca27a1dafb3819)

[Compare
Source](https://redirect.github.com/kaelzhang/node-ignore/compare/6.0.1...ee70c66d32e900f6e793c733a4ca27a1dafb3819)

###
[`v6.0.1`](https://redirect.github.com/kaelzhang/node-ignore/releases/tag/6.0.1):
6.x (&#x3D;&#x3D; 5.3.2)

[Compare
Source](https://redirect.github.com/kaelzhang/node-ignore/compare/6.0.0...6.0.1)

### 6.x

-   The release of `6.x` is due to a mistake.
- Making an upgrade from `5.x` to 6.x for now actually changes nothing
and does no harm, everyone could just upgrade or ignore the version.
    -   Actually `6.0.2` is `5.3.2`
-   The next major release will be `7.0.0`

###
[`v6.0.0`](https://redirect.github.com/kaelzhang/node-ignore/compare/5.3.2...6.0.0)

[Compare
Source](https://redirect.github.com/kaelzhang/node-ignore/compare/5.3.2...6.0.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-31 15:38:37 -04:00
Eli Bosley
dc9d5ad661 chore: fix license path in readme 2025-03-31 15:16:05 -04:00
Pujit Mehrotra
4964cf557b chore: update license fields in package.json (#1298)
Sets license for all node.js packages to `GPL-2.0-or-later`

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Chores**
- Simplified license compliance verification by removing legacy script
logic.
- Updated licensing terms across components to GPL-2.0-or-later for
broader compatibility.
- **Documentation**
- Revised setup instructions to indicate that the use of the Just build
tool is now optional.
- **New Features**
- Added fallback support in the build automation tool to ensure smoother
operations when targets are missing.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-03-31 14:52:49 -04:00
Zack Spear
e54f189630 feat: copy to webgui repo script docs + wc build options (#1285)
Previously the historical script only use to copy built web components
into the webgui repo.

The new script provides additional commands to find files in the API
repo's plugin dir and attempts to find "new" files. Then a command to
act upon each of these new file to sync in either direction, skip it, or
ignore it.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Introduced an interactive synchronization tool that streamlines file
transfers between projects.
- Added a new command to easily trigger the synchronization process,
leveraging enhanced file management and notification capabilities.

- **Chores**
- Updated version control settings to ignore temporary synchronization
files.
  - Removed an outdated file copying script for improved maintenance.
  - Added new dependencies to support enhanced functionality.
- Modified a script to exclude specific files from deletion during the
activation code setup process.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-03-31 14:36:33 -04:00
Pujit Mehrotra
9f7218da79 chore: update license to GPL-2.0-or-later (#1295)
to accomodate GPL-3.0 based dependencies.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Documentation**
- Revised licensing documentation to clearly state that the project is
distributed under GNU GPL v2 (or later) with complete terms provided.
- **Chores**
  - Updated overall license declarations to a more flexible version.
- Introduced new compliance tools to automatically verify that
dependency licenses meet the accepted criteria.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-03-31 14:34:33 -04:00
Eli Bosley
d5a3d0dfac fix: OEM plugin issues (#1288)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- The file synchronization tool now requires an explicitly defined
destination and offers a new option to remove remote password files
before syncing. Additionally, synchronization now omits ownership,
group, and permission metadata for smoother transfers.
- The activation flow has been refined, with legacy authentication
modifications removed to deliver a cleaner welcome modal experience.
- A new variable has been introduced to enhance server state management.

- **Refactor**
- Internal configuration adjustments have been made to enhance component
delivery and streamline system actions.

- **Bug Fixes**
- Updated handling of remote user and host parameters in the
synchronization script for improved functionality.
- Simplified the activation code removal process by focusing solely on
the `.set-password.php` file restoration.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Zack Spear <hi@zackspear.com>
2025-03-28 16:39:15 -04:00
Pujit Mehrotra
2266139742 fix: extract callbacks to library (#1280)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Chores**
  - Updated environment configuration to enhance secure handling.
  - Integrated a shared dependency for consistent callback management.

- **Refactor**
  - Streamlined callback actions management for improved performance.
- Upgraded the operating system version from a beta release to stable
(7.0.0), delivering enhanced reliability.
- Centralized callback actions store usage across components for better
state management.
- Removed deprecated callback management code to improve clarity and
maintainability.

- **New Features**
- Introduced a new redirect component to enhance user navigation
experience.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Eli Bosley <ekbosley@gmail.com>
Co-authored-by: Zack Spear <hi@zackspear.com>
2025-03-28 16:11:29 -04:00
Pujit Mehrotra
7fb78494cb fix(api): redirect benign pnpm postinstall warning to log file (#1290)
which lives at `/var/log/unraid-api/build-scripts.log`
2025-03-28 13:50:41 -04:00
Pujit Mehrotra
2f09445f2e feat(api): add unraid-api --delete command (#1289)
- Added a `command:raw` package.json script to let devs run `dist/cli.js` without rebuilding, enabling experimentation in the transpiled script.
- `unraid-api --delete` allows users to select and remove keys with confirmation
prompts.
2025-03-28 10:17:22 -04:00
Eli Bosley
fa6a5c56b6 chore: update ranging strategy for renovate (#1286)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Chores**
- Updated the dependency update configuration to adopt a replace
strategy for version ranges, ensuring smoother and clearer version
management.
- Added a new dependency, `@unraid/shared-callbacks`, for enhanced
functionality.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-03-28 10:12:07 -04:00
Eli Bosley
234017a828 chore: add self to work intent template 2025-03-27 17:12:32 -04:00
Eli Bosley
0210b9e62e chore: wrong charactrer 2025-03-27 17:11:17 -04:00
Eli Bosley
4b2763c7f9 fix: additional url fixes 2025-03-27 17:10:51 -04:00
Eli Bosley
ed44796d5d Update readme.md 2025-03-27 17:07:49 -04:00
Pujit Mehrotra
d23a89f0b3 chore: re-add .env.staging in api 2025-03-27 16:01:38 -04:00
Pujit Mehrotra
d0d2ff65ed fix: replace files lost during pruning 2025-03-27 15:47:29 -04:00
Pujit Mehrotra
9f492bf217 feat: api plugin system & offline versioned dependency vendoring (#1252)
- **New Features**
- Created a dynamic plugin system for the API to enable community
augmentation of GraphQL, CLI, and Cron functionalities capabilities.
- Included an example plugin under `packages/unraid-api-plugin-health`
that adds a new graphql query for API health checks.
- Added `rc.unraid-api` commands for backing up, restoring, and
installing production dependencies, streamlining maintenance and
deployment.
- Improved dependency vendoring by bundling a versioned pnpm store
(instead of `node_modules`). Versioning will allow users to add plugins
to a specific api release without requiring an internet connection on
subsequent reboots.

- **Chores**
- Upgraded build workflows and versioning processes to ensure more
reliable artifact handling and production packaging.
2025-03-27 13:23:55 -04:00
github-actions[bot]
c4b4d26af0 chore(main): release 4.4.1 (#1270)
🤖 I have created a release *beep* *boop*
---


## [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))
([49f6365](49f636541b))
* patch version override logic incorrect
([#1275](https://github.com/unraid/api/issues/1275))
([0bcfb47](0bcfb47bbc))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-03-26 20:01:06 -04:00
Eli Bosley
0bcfb47bbc fix: patch version override logic incorrect (#1275)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Bug Fixes**
- Improved the system’s version update mechanism so that updates are
applied only when the current system version matches the expected
version. This enhancement ensures more consistent and reliable version
checks during the update process.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-03-26 17:57:30 -04:00
Michael Datelle
b0099421f3 refactor: swap out radix with reka (#1271)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **Refactor**
- Improved type safety and consistency across UI components by
leveraging centralized type definitions.

- **Chores**
- Updated and consolidated UI component dependencies by migrating from a
previous library to a new one and refining package configurations.

- **Style**
- Standardized code formatting for uniform syntax and improved
readability.

- **Tests**
- Expanded testing configuration to include additional file types for
enhanced test coverage.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: mdatelle <mike@datelle.net>
2025-03-26 14:56:43 -04:00
Zack Spear
49f636541b fix: .env.production from allowing console logs on build (#1273)
`VITE_ALLOW_CONSOLE_LOGS` should not be present in `.env.production`. We
don't want basic debugs logs in prod.

Found this because the latest OS release `7.1.0-beta.1.6` which included
the latest web components had debug logs included.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Chores**
- Disabled non-essential console logging in the production environment
for a cleaner runtime experience.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-03-26 09:16:14 -04:00
github-actions[bot]
419c794e03 chore(main): release 4.4.0 (#1241)
🤖 I have created a release *beep* *boop*
---


## [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))
([7e6be67](7e6be67f61))
* downgrade page replace key check
([#1263](https://github.com/unraid/api/issues/1263))
([6a92f61](6a92f61f1a))
* make log viewer component dynamic
([#1242](https://github.com/unraid/api/issues/1242))
([a356bf0](a356bf03fb))
* ReplaceKey functionality in Registration and Update pages
([#1246](https://github.com/unraid/api/issues/1246))
([f3e6a00](f3e6a0011e))
* UnraidCheckExec for Check OS Updates via UPC dropdown
([#1265](https://github.com/unraid/api/issues/1265))
([3a20930](3a20930ead))


### Bug Fixes

* **deps:** update all non-major dependencies
([#1236](https://github.com/unraid/api/issues/1236))
([9d63e56](9d63e56374))
* **deps:** update all non-major dependencies
([#1247](https://github.com/unraid/api/issues/1247))
([57a6c49](57a6c49f8a))
* **deps:** update all non-major dependencies
([#1251](https://github.com/unraid/api/issues/1251))
([ad3906e](ad3906e682))
* **deps:** update all non-major dependencies
([#1253](https://github.com/unraid/api/issues/1253))
([bbb02e9](bbb02e991c))
* **deps:** update dependency @nestjs/passport to v11
([#1244](https://github.com/unraid/api/issues/1244))
([9e54237](9e54237670))
* **deps:** update dependency graphql-subscriptions to v3
([#1209](https://github.com/unraid/api/issues/1209))
([c9789ac](c9789ac1f2))
* **deps:** update dependency ini to v5
([#1217](https://github.com/unraid/api/issues/1217))
([590ab73](590ab7327f))
* **deps:** update dependency jose to v6
([#1248](https://github.com/unraid/api/issues/1248))
([03ece33](03ece335b8))
* **deps:** update dependency marked to v15
([#1249](https://github.com/unraid/api/issues/1249))
([8f78b3f](8f78b3f1ca))
* **deps:** update dependency pino-pretty to v13
([#1250](https://github.com/unraid/api/issues/1250))
([1892e23](1892e23c22))
* **deps:** update dependency pm2 to v6
([#1258](https://github.com/unraid/api/issues/1258))
([d8afc8f](d8afc8f4c9))
* **deps:** update dependency shadcn-vue to v1
([#1259](https://github.com/unraid/api/issues/1259))
([cb2020d](cb2020dee6))
* **deps:** update dependency vue-i18n to v11
([#1261](https://github.com/unraid/api/issues/1261))
([2c01ba9](2c01ba9610))
* **deps:** update vueuse monorepo to v13 (major)
([#1262](https://github.com/unraid/api/issues/1262))
([9ce10a7](9ce10a72b2))
* make scripts executable when building the plugin
([#1255](https://github.com/unraid/api/issues/1255))
([7bc9949](7bc9949110))
* node installation not persisting across reboots
([#1256](https://github.com/unraid/api/issues/1256))
([3bfcc8e](3bfcc8e8c0))
* update configValid state to ineligible in var.ini and adjust rel…
([#1268](https://github.com/unraid/api/issues/1268))
([cc85fba](cc85fba207))

---
This PR was generated with [Release
Please](https://github.com/googleapis/release-please). See
[documentation](https://github.com/googleapis/release-please#release-please).

Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
2025-03-25 09:43:58 -04:00
renovate[bot]
bbb02e991c fix(deps): update all non-major dependencies (#1253)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@apollo/client](https://www.apollographql.com/docs/react/)
([source](https://redirect.github.com/apollographql/apollo-client)) |
[`3.13.4` ->
`3.13.5`](https://renovatebot.com/diffs/npm/@apollo%2fclient/3.13.4/3.13.5)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@apollo%2fclient/3.13.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@apollo%2fclient/3.13.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@apollo%2fclient/3.13.4/3.13.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@apollo%2fclient/3.13.4/3.13.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [@eslint/js](https://eslint.org)
([source](https://redirect.github.com/eslint/eslint/tree/HEAD/packages/js))
| [`9.22.0` ->
`9.23.0`](https://renovatebot.com/diffs/npm/@eslint%2fjs/9.22.0/9.23.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@eslint%2fjs/9.23.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@eslint%2fjs/9.23.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@eslint%2fjs/9.22.0/9.23.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@eslint%2fjs/9.22.0/9.23.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [@nestjs/apollo](https://redirect.github.com/nestjs/graphql) |
[`13.0.3` ->
`13.0.4`](https://renovatebot.com/diffs/npm/@nestjs%2fapollo/13.0.3/13.0.4)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2fapollo/13.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2fapollo/13.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2fapollo/13.0.3/13.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2fapollo/13.0.3/13.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [@nestjs/common](https://nestjs.com)
([source](https://redirect.github.com/nestjs/nest/tree/HEAD/packages/common))
| [`11.0.11` ->
`11.0.12`](https://renovatebot.com/diffs/npm/@nestjs%2fcommon/11.0.11/11.0.12)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2fcommon/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2fcommon/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2fcommon/11.0.11/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2fcommon/11.0.11/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [@nestjs/core](https://nestjs.com)
([source](https://redirect.github.com/nestjs/nest/tree/HEAD/packages/core))
| [`11.0.11` ->
`11.0.12`](https://renovatebot.com/diffs/npm/@nestjs%2fcore/11.0.11/11.0.12)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2fcore/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2fcore/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2fcore/11.0.11/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2fcore/11.0.11/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [@nestjs/graphql](https://redirect.github.com/nestjs/graphql) |
[`13.0.3` ->
`13.0.4`](https://renovatebot.com/diffs/npm/@nestjs%2fgraphql/13.0.3/13.0.4)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2fgraphql/13.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2fgraphql/13.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2fgraphql/13.0.3/13.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2fgraphql/13.0.3/13.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [@nestjs/platform-fastify](https://nestjs.com)
([source](https://redirect.github.com/nestjs/nest/tree/HEAD/packages/platform-fastify))
| [`11.0.11` ->
`11.0.12`](https://renovatebot.com/diffs/npm/@nestjs%2fplatform-fastify/11.0.11/11.0.12)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2fplatform-fastify/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2fplatform-fastify/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2fplatform-fastify/11.0.11/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2fplatform-fastify/11.0.11/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [@nestjs/testing](https://nestjs.com)
([source](https://redirect.github.com/nestjs/nest/tree/HEAD/packages/testing))
| [`11.0.11` ->
`11.0.12`](https://renovatebot.com/diffs/npm/@nestjs%2ftesting/11.0.11/11.0.12)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2ftesting/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2ftesting/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2ftesting/11.0.11/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2ftesting/11.0.11/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [@nuxt/devtools](https://devtools.nuxt.com)
([source](https://redirect.github.com/nuxt/devtools/tree/HEAD/packages/devtools))
| [`2.3.0` ->
`2.3.1`](https://renovatebot.com/diffs/npm/@nuxt%2fdevtools/2.3.0/2.3.1)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@nuxt%2fdevtools/2.3.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nuxt%2fdevtools/2.3.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nuxt%2fdevtools/2.3.0/2.3.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nuxt%2fdevtools/2.3.0/2.3.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [@rollup/rollup-linux-x64-gnu](https://rollupjs.org/)
([source](https://redirect.github.com/rollup/rollup)) | [`4.36.0` ->
`4.37.0`](https://renovatebot.com/diffs/npm/@rollup%2frollup-linux-x64-gnu/4.36.0/4.37.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@rollup%2frollup-linux-x64-gnu/4.37.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@rollup%2frollup-linux-x64-gnu/4.37.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@rollup%2frollup-linux-x64-gnu/4.36.0/4.37.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@rollup%2frollup-linux-x64-gnu/4.36.0/4.37.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@storybook/addon-essentials](https://redirect.github.com/storybookjs/storybook/tree/next/code/addons/essentials)
([source](https://redirect.github.com/storybookjs/storybook/tree/HEAD/code/addons/essentials))
| [`8.6.7` ->
`8.6.9`](https://renovatebot.com/diffs/npm/@storybook%2faddon-essentials/8.6.7/8.6.9)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@storybook%2faddon-essentials/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@storybook%2faddon-essentials/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@storybook%2faddon-essentials/8.6.7/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@storybook%2faddon-essentials/8.6.7/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@storybook/addon-interactions](https://redirect.github.com/storybookjs/storybook/tree/next/code/addons/interactions)
([source](https://redirect.github.com/storybookjs/storybook/tree/HEAD/code/addons/interactions))
| [`8.6.7` ->
`8.6.9`](https://renovatebot.com/diffs/npm/@storybook%2faddon-interactions/8.6.7/8.6.9)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@storybook%2faddon-interactions/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@storybook%2faddon-interactions/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@storybook%2faddon-interactions/8.6.7/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@storybook%2faddon-interactions/8.6.7/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@storybook/addon-links](https://redirect.github.com/storybookjs/storybook/tree/next/code/addons/links)
([source](https://redirect.github.com/storybookjs/storybook/tree/HEAD/code/addons/links))
| [`8.6.7` ->
`8.6.9`](https://renovatebot.com/diffs/npm/@storybook%2faddon-links/8.6.7/8.6.9)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@storybook%2faddon-links/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@storybook%2faddon-links/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@storybook%2faddon-links/8.6.7/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@storybook%2faddon-links/8.6.7/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@storybook/builder-vite](https://redirect.github.com/storybookjs/storybook/tree/next/code/builders/builder-vite/#readme)
([source](https://redirect.github.com/storybookjs/storybook/tree/HEAD/code/builders/builder-vite))
| [`8.6.7` ->
`8.6.9`](https://renovatebot.com/diffs/npm/@storybook%2fbuilder-vite/8.6.7/8.6.9)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@storybook%2fbuilder-vite/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@storybook%2fbuilder-vite/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@storybook%2fbuilder-vite/8.6.7/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@storybook%2fbuilder-vite/8.6.7/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@storybook/vue3-vite](https://redirect.github.com/storybookjs/storybook/tree/next/code/frameworks/vue3-vite)
([source](https://redirect.github.com/storybookjs/storybook/tree/HEAD/code/frameworks/vue3-vite))
| [`8.6.7` ->
`8.6.9`](https://renovatebot.com/diffs/npm/@storybook%2fvue3-vite/8.6.7/8.6.9)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@storybook%2fvue3-vite/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@storybook%2fvue3-vite/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@storybook%2fvue3-vite/8.6.7/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@storybook%2fvue3-vite/8.6.7/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [@swc/core](https://swc.rs)
([source](https://redirect.github.com/swc-project/swc)) | [`1.11.11` ->
`1.11.13`](https://renovatebot.com/diffs/npm/@swc%2fcore/1.11.11/1.11.13)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@swc%2fcore/1.11.13?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@swc%2fcore/1.11.13?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@swc%2fcore/1.11.11/1.11.13?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@swc%2fcore/1.11.11/1.11.13?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@types/diff](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/diff)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/diff))
| [`7.0.1` ->
`7.0.2`](https://renovatebot.com/diffs/npm/@types%2fdiff/7.0.1/7.0.2) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fdiff/7.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fdiff/7.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fdiff/7.0.1/7.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fdiff/7.0.1/7.0.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@types/node](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node)
([source](https://redirect.github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/node))
| [`22.13.10` ->
`22.13.13`](https://renovatebot.com/diffs/npm/@types%2fnode/22.13.10/22.13.13)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fnode/22.13.13?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fnode/22.13.13?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fnode/22.13.10/22.13.13?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fnode/22.13.10/22.13.13?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [eslint](https://eslint.org)
([source](https://redirect.github.com/eslint/eslint)) | [`9.22.0` ->
`9.23.0`](https://renovatebot.com/diffs/npm/eslint/9.22.0/9.23.0) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint/9.23.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint/9.23.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint/9.22.0/9.23.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint/9.22.0/9.23.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[eslint-plugin-prettier](https://redirect.github.com/prettier/eslint-plugin-prettier)
| [`5.2.3` ->
`5.2.5`](https://renovatebot.com/diffs/npm/eslint-plugin-prettier/5.2.3/5.2.5)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/eslint-plugin-prettier/5.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/eslint-plugin-prettier/5.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/eslint-plugin-prettier/5.2.3/5.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/eslint-plugin-prettier/5.2.3/5.2.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [graphql-scalars](https://redirect.github.com/Urigo/graphql-scalars) |
[`1.24.1` ->
`1.24.2`](https://renovatebot.com/diffs/npm/graphql-scalars/1.24.1/1.24.2)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/graphql-scalars/1.24.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/graphql-scalars/1.24.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/graphql-scalars/1.24.1/1.24.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/graphql-scalars/1.24.1/1.24.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [nestjs-pino](https://redirect.github.com/iamolegga/nestjs-pino) |
[`4.3.1` ->
`4.4.0`](https://renovatebot.com/diffs/npm/nestjs-pino/4.3.1/4.4.0) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/nestjs-pino/4.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/nestjs-pino/4.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/nestjs-pino/4.3.1/4.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/nestjs-pino/4.3.1/4.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [nuxt](https://nuxt.com)
([source](https://redirect.github.com/nuxt/nuxt/tree/HEAD/packages/nuxt))
| [`3.16.0` ->
`3.16.1`](https://renovatebot.com/diffs/npm/nuxt/3.16.0/3.16.1) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/nuxt/3.16.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/nuxt/3.16.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/nuxt/3.16.0/3.16.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/nuxt/3.16.0/3.16.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [reka-ui](https://redirect.github.com/unovue/reka-ui) | [`2.1.0` ->
`2.1.1`](https://renovatebot.com/diffs/npm/reka-ui/2.1.0/2.1.1) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/reka-ui/2.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/reka-ui/2.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/reka-ui/2.1.0/2.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/reka-ui/2.1.0/2.1.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[storybook](https://redirect.github.com/storybookjs/storybook/tree/next/code/lib/cli)
([source](https://redirect.github.com/storybookjs/storybook/tree/HEAD/code/lib/cli))
| [`8.6.7` ->
`8.6.9`](https://renovatebot.com/diffs/npm/storybook/8.6.7/8.6.9) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/storybook/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/storybook/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/storybook/8.6.7/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/storybook/8.6.7/8.6.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[typescript-eslint](https://typescript-eslint.io/packages/typescript-eslint)
([source](https://redirect.github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/typescript-eslint))
| [`8.26.1` ->
`8.28.0`](https://renovatebot.com/diffs/npm/typescript-eslint/8.26.1/8.28.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/typescript-eslint/8.28.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/typescript-eslint/8.28.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/typescript-eslint/8.26.1/8.28.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/typescript-eslint/8.26.1/8.28.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [vite](https://vite.dev)
([source](https://redirect.github.com/vitejs/vite/tree/HEAD/packages/vite))
| [`6.2.2` ->
`6.2.3`](https://renovatebot.com/diffs/npm/vite/6.2.2/6.2.3) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/vite/6.2.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vite/6.2.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vite/6.2.2/6.2.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vite/6.2.2/6.2.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [vitest](https://redirect.github.com/vitest-dev/vitest)
([source](https://redirect.github.com/vitest-dev/vitest/tree/HEAD/packages/vitest))
| [`3.0.7` ->
`3.0.9`](https://renovatebot.com/diffs/npm/vitest/3.0.7/3.0.9) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/vitest/3.0.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vitest/3.0.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vitest/3.0.7/3.0.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vitest/3.0.7/3.0.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [vuetify](https://vuetifyjs.com)
([source](https://redirect.github.com/vuetifyjs/vuetify/tree/HEAD/packages/vuetify))
| [`3.7.17` ->
`3.7.18`](https://renovatebot.com/diffs/npm/vuetify/3.7.17/3.7.18) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/vuetify/3.7.18?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vuetify/3.7.18?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vuetify/3.7.17/3.7.18?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vuetify/3.7.17/3.7.18?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [zx](https://google.github.io/zx/)
([source](https://redirect.github.com/google/zx)) | [`8.3.2` ->
`8.4.1`](https://renovatebot.com/diffs/npm/zx/8.3.2/8.4.1) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/zx/8.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/zx/8.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/zx/8.3.2/8.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/zx/8.3.2/8.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>apollographql/apollo-client (@&#8203;apollo/client)</summary>

###
[`v3.13.5`](https://redirect.github.com/apollographql/apollo-client/blob/HEAD/CHANGELOG.md#3135)

[Compare
Source](https://redirect.github.com/apollographql/apollo-client/compare/v3.13.4...v3.13.5)

##### Patch Changes

-
[#&#8203;12461](https://redirect.github.com/apollographql/apollo-client/pull/12461)
[`12c8d06`](12c8d06f1e)
Thanks [@&#8203;jerelmiller](https://redirect.github.com/jerelmiller)! -
Fix an issue where a `cache-first` query would return the result for
previous variables when a cache update is issued after simultaneously
changing variables and skipping the query.

</details>

<details>
<summary>eslint/eslint (@&#8203;eslint/js)</summary>

###
[`v9.23.0`](https://redirect.github.com/eslint/eslint/compare/v9.22.0...20591c49ff27435b1555111a929a6966febc249f)

[Compare
Source](https://redirect.github.com/eslint/eslint/compare/v9.22.0...v9.23.0)

</details>

<details>
<summary>nestjs/graphql (@&#8203;nestjs/apollo)</summary>

###
[`v13.0.4`](https://redirect.github.com/nestjs/graphql/releases/tag/v13.0.4)

[Compare
Source](https://redirect.github.com/nestjs/graphql/compare/v13.0.3...v13.0.4)

##### 13.0.4 (2025-03-24)

##### Enhancements

-   `graphql`
- [#&#8203;3503](https://redirect.github.com/nestjs/graphql/pull/3503)
feat(graphql): add support for transforming the resolvers
([@&#8203;JoshVee](https://redirect.github.com/JoshVee))

##### Dependencies

-   `graphql`
- [#&#8203;3487](https://redirect.github.com/nestjs/graphql/pull/3487)
fix(deps): update dependency ws to v8.18.1
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
- [#&#8203;3488](https://redirect.github.com/nestjs/graphql/pull/3488)
fix(deps): update graphql-tools monorepo
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))
-   `mercurius`
- [#&#8203;3494](https://redirect.github.com/nestjs/graphql/pull/3494)
chore(deps): update dependency mercurius to v16.1.0
([@&#8203;renovate\[bot\]](https://redirect.github.com/apps/renovate))

##### Committers: 1

- Josh Vawdrey ([@&#8203;JoshVee](https://redirect.github.com/JoshVee))

</details>

<details>
<summary>nestjs/nest (@&#8203;nestjs/common)</summary>

###
[`v11.0.12`](https://redirect.github.com/nestjs/nest/compare/v11.0.11...c58f49a3cc7b48916a98dcb81764ce77950d535a)

[Compare
Source](https://redirect.github.com/nestjs/nest/compare/v11.0.11...v11.0.12)

</details>

<details>
<summary>nestjs/nest (@&#8203;nestjs/core)</summary>

###
[`v11.0.12`](https://redirect.github.com/nestjs/nest/compare/v11.0.11...c58f49a3cc7b48916a98dcb81764ce77950d535a)

[Compare
Source](https://redirect.github.com/nestjs/nest/compare/v11.0.11...v11.0.12)

</details>

<details>
<summary>nestjs/nest (@&#8203;nestjs/platform-fastify)</summary>

###
[`v11.0.12`](https://redirect.github.com/nestjs/nest/releases/tag/v11.0.12)

[Compare
Source](https://redirect.github.com/nestjs/nest/compare/v11.0.11...v11.0.12)

#### v11.0.12 (2025-03-19)

##### Bug fixes

-   `core`
- [#&#8203;14803](https://redirect.github.com/nestjs/nest/pull/14803)
fix(core): infinite loop on broken circular reference
([@&#8203;kamilmysliwiec](https://redirect.github.com/kamilmysliwiec))
-
[https://github.com/nestjs/nest/pull/14792](https://redirect.github.com/nestjs/nest/pull/14792)
dependencies not resolving for request-scoped lazy providers
([@&#8203;anizozina](https://redirect.github.com/anizozina))

##### Enhancements

-   `core`
- [#&#8203;14802](https://redirect.github.com/nestjs/nest/pull/14802)
feat(core): add options to the legacy route converter
([@&#8203;kamilmysliwiec](https://redirect.github.com/kamilmysliwiec))

</details>

<details>
<summary>nestjs/nest (@&#8203;nestjs/testing)</summary>

###
[`v11.0.12`](https://redirect.github.com/nestjs/nest/compare/v11.0.11...c58f49a3cc7b48916a98dcb81764ce77950d535a)

[Compare
Source](https://redirect.github.com/nestjs/nest/compare/v11.0.11...v11.0.12)

</details>

<details>
<summary>nuxt/devtools (@&#8203;nuxt/devtools)</summary>

###
[`v2.3.1`](https://redirect.github.com/nuxt/devtools/blob/HEAD/CHANGELOG.md#231-2025-03-20)

[Compare
Source](https://redirect.github.com/nuxt/devtools/compare/v2.3.0...v2.3.1)

##### Bug Fixes

- downgrade `execa` to be compatible with Node v18, fix
[#&#8203;821](https://redirect.github.com/nuxt/devtools/issues/821)
([f15c7dc](f15c7dca3a))

</details>

<details>
<summary>rollup/rollup (@&#8203;rollup/rollup-linux-x64-gnu)</summary>

###
[`v4.37.0`](https://redirect.github.com/rollup/rollup/blob/HEAD/CHANGELOG.md#4370)

[Compare
Source](https://redirect.github.com/rollup/rollup/compare/v4.36.0...v4.37.0)

*2025-03-23*

##### Features

- Support Musl Linux on Riscv64 architectures
([#&#8203;5726](https://redirect.github.com/rollup/rollup/issues/5726))
- Handles class decorators placed before the `export` keyword
([#&#8203;5871](https://redirect.github.com/rollup/rollup/issues/5871))

##### Bug Fixes

- Log Rust panic messages to the console when using the WASM build
([#&#8203;5875](https://redirect.github.com/rollup/rollup/issues/5875))

##### Pull Requests

- [#&#8203;5726](https://redirect.github.com/rollup/rollup/pull/5726):
Add support for linux riscv64 musl
([@&#8203;fossdd](https://redirect.github.com/fossdd),
[@&#8203;leso-kn](https://redirect.github.com/leso-kn))
- [#&#8203;5871](https://redirect.github.com/rollup/rollup/pull/5871):
feat: support decorators before or after export
([@&#8203;TrickyPi](https://redirect.github.com/TrickyPi))
- [#&#8203;5875](https://redirect.github.com/rollup/rollup/pull/5875):
capture Rust panic messages and output them to the console.
([@&#8203;luyahan](https://redirect.github.com/luyahan),
[@&#8203;lukastaegert](https://redirect.github.com/lukastaegert))
- [#&#8203;5883](https://redirect.github.com/rollup/rollup/pull/5883):
Pin digest of 3rd party actions
([@&#8203;re-taro](https://redirect.github.com/re-taro))
- [#&#8203;5885](https://redirect.github.com/rollup/rollup/pull/5885):
fix(deps): lock file maintenance minor/patch updates
([@&#8203;renovate](https://redirect.github.com/renovate)\[bot])

</details>

<details>
<summary>storybookjs/storybook
(@&#8203;storybook/addon-essentials)</summary>

###
[`v8.6.9`](https://redirect.github.com/storybookjs/storybook/blob/HEAD/CHANGELOG.md#869)

[Compare
Source](https://redirect.github.com/storybookjs/storybook/compare/v8.6.8...v8.6.9)

- Next: Fix react aliases in next vite plugin -
[#&#8203;30914](https://redirect.github.com/storybookjs/storybook/pull/30914),
thanks [@&#8203;kasperpeulen](https://redirect.github.com/kasperpeulen)!

###
[`v8.6.8`](https://redirect.github.com/storybookjs/storybook/blob/HEAD/CHANGELOG.md#868)

[Compare
Source](https://redirect.github.com/storybookjs/storybook/compare/v8.6.7...v8.6.8)

- Angular: Export all files in Angular package.json -
[#&#8203;30849](https://redirect.github.com/storybookjs/storybook/pull/30849),
thanks [@&#8203;kasperpeulen](https://redirect.github.com/kasperpeulen)!
- CLI: Don't add packageManager entry to package.json automatically -
[#&#8203;30855](https://redirect.github.com/storybookjs/storybook/pull/30855),
thanks [@&#8203;kasperpeulen](https://redirect.github.com/kasperpeulen)!
- React: Allow portable stories to be used in SSR -
[#&#8203;30847](https://redirect.github.com/storybookjs/storybook/pull/30847),
thanks [@&#8203;kasperpeulen](https://redirect.github.com/kasperpeulen)!
- Svelte: Adjust Svelte typings to include Svelte 5 function components
-
[#&#8203;30852](https://redirect.github.com/storybookjs/storybook/pull/30852),
thanks [@&#8203;dummdidumm](https://redirect.github.com/dummdidumm)!
- Telemetry: Make sure that telemetry doesn't fail on init -
[#&#8203;30857](https://redirect.github.com/storybookjs/storybook/pull/30857),
thanks [@&#8203;kasperpeulen](https://redirect.github.com/kasperpeulen)!
- Vite: Update HMR filter to target specific story file types -
[#&#8203;30845](https://redirect.github.com/storybookjs/storybook/pull/30845),
thanks [@&#8203;kasperpeulen](https://redirect.github.com/kasperpeulen)!

</details>

<details>
<summary>storybookjs/storybook (@&#8203;storybook/addon-links)</summary>

###
[`v8.6.9`](https://redirect.github.com/storybookjs/storybook/compare/v8.6.8...207c2f46348303bf86950865cf7a193b5a60ab69)

[Compare
Source](https://redirect.github.com/storybookjs/storybook/compare/v8.6.8...v8.6.9)

###
[`v8.6.8`](https://redirect.github.com/storybookjs/storybook/blob/HEAD/CHANGELOG.md#868)

[Compare
Source](https://redirect.github.com/storybookjs/storybook/compare/v8.6.7...v8.6.8)

- Angular: Export all files in Angular package.json -
[#&#8203;30849](https://redirect.github.com/storybookjs/storybook/pull/30849),
thanks [@&#8203;kasperpeulen](https://redirect.github.com/kasperpeulen)!
- CLI: Don't add packageManager entry to package.json automatically -
[#&#8203;30855](https://redirect.github.com/storybookjs/storybook/pull/30855),
thanks [@&#8203;kasperpeulen](https://redirect.github.com/kasperpeulen)!
- React: Allow portable stories to be used in SSR -
[#&#8203;30847](https://redirect.github.com/storybookjs/storybook/pull/30847),
thanks [@&#8203;kasperpeulen](https://redirect.github.com/kasperpeulen)!
- Svelte: Adjust Svelte typings to include Svelte 5 function components
-
[#&#8203;30852](https://redirect.github.com/storybookjs/storybook/pull/30852),
thanks [@&#8203;dummdidumm](https://redirect.github.com/dummdidumm)!
- Telemetry: Make sure that telemetry doesn't fail on init -
[#&#8203;30857](https://redirect.github.com/storybookjs/storybook/pull/30857),
thanks [@&#8203;kasperpeulen](https://redirect.github.com/kasperpeulen)!
- Vite: Update HMR filter to target specific story file types -
[#&#8203;30845](https://redirect.github.com/storybookjs/storybook/pull/30845),
thanks [@&#8203;kasperpeulen](https://redirect.github.com/kasperpeulen)!

</details>

<details>
<summary>swc-project/swc (@&#8203;swc/core)</summary>

###
[`v1.11.13`](https://redirect.github.com/swc-project/swc/blob/HEAD/CHANGELOG.md#11113---2025-03-24)

[Compare
Source](https://redirect.github.com/swc-project/swc/compare/v1.11.12...v1.11.13)

##### Features

- **(es/minifier)** Merge alt's cons with cons
([#&#8203;10256](https://redirect.github.com/swc-project/swc/issues/10256))
([589bcd7](589bcd70c4))

- **(swc_core)** Expose features of `swc_parallel`
([#&#8203;10258](https://redirect.github.com/swc-project/swc/issues/10258))
([042f19f](042f19ff66))

##### Performance

- **(es/minifier)** Merge `expr_simplifier` into pure optimizer
([#&#8203;10202](https://redirect.github.com/swc-project/swc/issues/10202))
([9c9b0ba](9c9b0baaac))

###
[`v1.11.12`](https://redirect.github.com/swc-project/swc/blob/HEAD/CHANGELOG.md#11112---2025-03-23)

[Compare
Source](https://redirect.github.com/swc-project/swc/compare/v1.11.11...v1.11.12)

##### Bug Fixes

- **(es/minifier)** Make `inline_globals` noop by default
([#&#8203;10231](https://redirect.github.com/swc-project/swc/issues/10231))
([b192dc8](b192dc82e6))

- **(es/minifier)** Fix access to `GLOBALS` in char freq compute
([#&#8203;10239](https://redirect.github.com/swc-project/swc/issues/10239))
([6286663](6286663868))

- **(es/parser)** Fix span of wrong `await` tokens
([#&#8203;10252](https://redirect.github.com/swc-project/swc/issues/10252))
([5c28dc3](5c28dc3964))

- **(es/types)** Fix broken types
([#&#8203;10224](https://redirect.github.com/swc-project/swc/issues/10224))
([540bdf8](540bdf868d))

##### Documentation

- **(es)** Improve documentation
([#&#8203;10247](https://redirect.github.com/swc-project/swc/issues/10247))
([549e38d](549e38db9e))

##### Features

- **(es/fast-lexer)** Enhance identifier handling with Unicode support
([#&#8203;10226](https://redirect.github.com/swc-project/swc/issues/10226))
([482b63a](482b63a905))

- **(es/minifier)** Invoke IIFE into block
([#&#8203;10220](https://redirect.github.com/swc-project/swc/issues/10220))
([c9a6c23](c9a6c23787))

- **(es/minifier)** Remove needless blocks
([#&#8203;10234](https://redirect.github.com/swc-project/swc/issues/10234))
([0817970](08179702bf))

- **(swc_parallel)** Introduce `rayon` mode
([#&#8203;10237](https://redirect.github.com/swc-project/swc/issues/10237))
([3c2213c](3c2213c829))

- **(ts/fast-strip)** Add start/end span information
([#&#8203;10251](https://redirect.github.com/swc-project/swc/issues/10251))
([ab39a62](ab39a62528))

- **(ts/fast-strip)** Improve error message snippet
([#&#8203;10253](https://redirect.github.com/swc-project/swc/issues/10253))
([f4f426c](f4f426c9c9))

- **(ts/fast-strip)** Remove line numbers
([#&#8203;10254](https://redirect.github.com/swc-project/swc/issues/10254))
([40e216d](40e216db82))

##### Performance

- **(es/minifier)** Merge `dead_branch_remover` into pure optimizer
([#&#8203;10201](https://redirect.github.com/swc-project/swc/issues/10201))
([6841523](6841523977))

</details>

<details>
<summary>eslint/eslint (eslint)</summary>

###
[`v9.23.0`](https://redirect.github.com/eslint/eslint/compare/v9.22.0...2aaadceec13e6df89a0c56e2b6ce4a145c1ac3aa)

[Compare
Source](https://redirect.github.com/eslint/eslint/compare/v9.22.0...v9.23.0)

</details>

<details>
<summary>prettier/eslint-plugin-prettier
(eslint-plugin-prettier)</summary>

###
[`v5.2.5`](https://redirect.github.com/prettier/eslint-plugin-prettier/blob/HEAD/CHANGELOG.md#525)

[Compare
Source](https://redirect.github.com/prettier/eslint-plugin-prettier/compare/v5.2.4...v5.2.5)

##### Patch Changes

-
[#&#8203;721](https://redirect.github.com/prettier/eslint-plugin-prettier/pull/721)
[`4f5513d`](4f5513de4c)
Thanks [@&#8203;JounQin](https://redirect.github.com/JounQin)! - fix:
clarify correct `eslint-config-prettier` peer range

###
[`v5.2.4`](https://redirect.github.com/prettier/eslint-plugin-prettier/blob/HEAD/CHANGELOG.md#524)

[Compare
Source](https://redirect.github.com/prettier/eslint-plugin-prettier/compare/v5.2.3...v5.2.4)

##### Patch Changes

-
[#&#8203;715](https://redirect.github.com/prettier/eslint-plugin-prettier/pull/715)
[`b8cfe56`](b8cfe56e34)
Thanks [@&#8203;JounQin](https://redirect.github.com/JounQin)! - chore:
hourcekeeping, bump all (dev) deps

</details>

<details>
<summary>Urigo/graphql-scalars (graphql-scalars)</summary>

###
[`v1.24.2`](https://redirect.github.com/Urigo/graphql-scalars/blob/HEAD/CHANGELOG.md#1242)

[Compare
Source](https://redirect.github.com/Urigo/graphql-scalars/compare/v1.24.1...v1.24.2)

##### Patch Changes

-
[#&#8203;2791](https://redirect.github.com/graphql-hive/graphql-scalars/pull/2791)

[`3e1e924`](3e1e924b93)
Thanks [@&#8203;dotansimha](https://redirect.github.com/dotansimha)! -
Enable npm provenance

</details>

<details>
<summary>iamolegga/nestjs-pino (nestjs-pino)</summary>

###
[`v4.4.0`](https://redirect.github.com/iamolegga/nestjs-pino/releases/tag/4.4.0):
: allow publishing source map files

[Compare
Source](https://redirect.github.com/iamolegga/nestjs-pino/compare/4.3.1...4.4.0)

#### What's Changed

- build(deps-dev): bump prettier from 3.5.1 to 3.5.2 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2255](https://redirect.github.com/iamolegga/nestjs-pino/pull/2255)
- build(deps-dev): bump
[@&#8203;eslint/js](https://redirect.github.com/eslint/js) from 9.20.0
to 9.21.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2256](https://redirect.github.com/iamolegga/nestjs-pino/pull/2256)
- build(deps-dev): bump
[@&#8203;types/node](https://redirect.github.com/types/node) from
22.13.4 to 22.13.5 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2257](https://redirect.github.com/iamolegga/nestjs-pino/pull/2257)
- build(deps-dev): bump ts-jest from 29.2.5 to 29.2.6 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2258](https://redirect.github.com/iamolegga/nestjs-pino/pull/2258)
- build(deps-dev): bump
[@&#8203;eslint/eslintrc](https://redirect.github.com/eslint/eslintrc)
from 3.2.0 to 3.3.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2261](https://redirect.github.com/iamolegga/nestjs-pino/pull/2261)
- build(deps-dev): bump
[@&#8203;eslint/compat](https://redirect.github.com/eslint/compat) from
1.2.6 to 1.2.7 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2262](https://redirect.github.com/iamolegga/nestjs-pino/pull/2262)
- build(deps-dev): bump rxjs from 7.8.1 to 7.8.2 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2259](https://redirect.github.com/iamolegga/nestjs-pino/pull/2259)
- build(deps-dev): bump eslint from 9.20.1 to 9.21.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2260](https://redirect.github.com/iamolegga/nestjs-pino/pull/2260)
- build(deps-dev): bump
[@&#8203;typescript-eslint/eslint-plugin](https://redirect.github.com/typescript-eslint/eslint-plugin)
from 8.24.1 to 8.25.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2263](https://redirect.github.com/iamolegga/nestjs-pino/pull/2263)
- build(deps-dev): bump
[@&#8203;typescript-eslint/parser](https://redirect.github.com/typescript-eslint/parser)
from 8.24.1 to 8.25.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2264](https://redirect.github.com/iamolegga/nestjs-pino/pull/2264)
- build(deps-dev): bump eslint-config-prettier from 10.0.1 to 10.0.2 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2265](https://redirect.github.com/iamolegga/nestjs-pino/pull/2265)
- build(deps-dev): bump
[@&#8203;nestjs/testing](https://redirect.github.com/nestjs/testing)
from 11.0.10 to 11.0.11 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2267](https://redirect.github.com/iamolegga/nestjs-pino/pull/2267)
- build(deps-dev): bump
[@&#8203;types/node](https://redirect.github.com/types/node) from
22.13.5 to 22.13.8 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2268](https://redirect.github.com/iamolegga/nestjs-pino/pull/2268)
- build(deps-dev): bump
[@&#8203;nestjs/platform-express](https://redirect.github.com/nestjs/platform-express)
from 11.0.10 to 11.0.11 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2269](https://redirect.github.com/iamolegga/nestjs-pino/pull/2269)
- build(deps-dev): bump prettier from 3.5.2 to 3.5.3 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2271](https://redirect.github.com/iamolegga/nestjs-pino/pull/2271)
- build(deps-dev): bump
[@&#8203;nestjs/core](https://redirect.github.com/nestjs/core) from
11.0.10 to 11.0.11 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2272](https://redirect.github.com/iamolegga/nestjs-pino/pull/2272)
- build(deps-dev): bump
[@&#8203;nestjs/platform-fastify](https://redirect.github.com/nestjs/platform-fastify)
from 11.0.10 to 11.0.11 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2273](https://redirect.github.com/iamolegga/nestjs-pino/pull/2273)
- build(deps-dev): bump
[@&#8203;nestjs/common](https://redirect.github.com/nestjs/common) from
11.0.10 to 11.0.11 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2274](https://redirect.github.com/iamolegga/nestjs-pino/pull/2274)
- build(deps-dev): bump
[@&#8203;types/node](https://redirect.github.com/types/node) from
22.13.8 to 22.13.9 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2275](https://redirect.github.com/iamolegga/nestjs-pino/pull/2275)
- build(deps-dev): bump
[@&#8203;typescript-eslint/eslint-plugin](https://redirect.github.com/typescript-eslint/eslint-plugin)
from 8.25.0 to 8.26.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2276](https://redirect.github.com/iamolegga/nestjs-pino/pull/2276)
- build(deps-dev): bump
[@&#8203;typescript-eslint/parser](https://redirect.github.com/typescript-eslint/parser)
from 8.25.0 to 8.26.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2277](https://redirect.github.com/iamolegga/nestjs-pino/pull/2277)
- build(deps-dev): bump eslint from 9.21.0 to 9.22.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2278](https://redirect.github.com/iamolegga/nestjs-pino/pull/2278)
- build(deps-dev): bump
[@&#8203;types/node](https://redirect.github.com/types/node) from
22.13.9 to 22.13.10 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2280](https://redirect.github.com/iamolegga/nestjs-pino/pull/2280)
- build(deps-dev): bump eslint-config-prettier from 10.0.2 to 10.1.1 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2281](https://redirect.github.com/iamolegga/nestjs-pino/pull/2281)
- build(deps-dev): bump
[@&#8203;typescript-eslint/parser](https://redirect.github.com/typescript-eslint/parser)
from 8.26.0 to 8.26.1 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2284](https://redirect.github.com/iamolegga/nestjs-pino/pull/2284)
- build(deps-dev): bump
[@&#8203;typescript-eslint/eslint-plugin](https://redirect.github.com/typescript-eslint/eslint-plugin)
from 8.26.0 to 8.26.1 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2285](https://redirect.github.com/iamolegga/nestjs-pino/pull/2285)
- build(deps-dev): bump typescript from 5.7.3 to 5.8.2 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2270](https://redirect.github.com/iamolegga/nestjs-pino/pull/2270)
- chore(package): allow publishing source map files by
[@&#8203;H4ad](https://redirect.github.com/H4ad) in
[https://github.com/iamolegga/nestjs-pino/pull/2288](https://redirect.github.com/iamolegga/nestjs-pino/pull/2288)

#### New Contributors

- [@&#8203;H4ad](https://redirect.github.com/H4ad) made their first
contribution in
[https://github.com/iamolegga/nestjs-pino/pull/2288](https://redirect.github.com/iamolegga/nestjs-pino/pull/2288)

**Full Changelog**:
https://github.com/iamolegga/nestjs-pino/compare/4.3.1...4.4.0

</details>

<details>
<summary>nuxt/nuxt (nuxt)</summary>

###
[`v3.16.1`](https://redirect.github.com/nuxt/nuxt/releases/tag/v3.16.1)

[Compare
Source](https://redirect.github.com/nuxt/nuxt/compare/v3.16.0...v3.16.1)

[compare
changes](https://redirect.github.com/nuxt/nuxt/compare/v3.16.0...v3.16.1)

##### 🔥 Performance

- **nuxt:** Use browser cache for payloads
([#&#8203;31379](https://redirect.github.com/nuxt/nuxt/pull/31379))

##### 🩹 Fixes

- **nuxt:** Restore nuxt aliases to nitro compilerOptions.paths
([#&#8203;31278](https://redirect.github.com/nuxt/nuxt/pull/31278))
- **nuxt:** Use new `mocked-exports`
([#&#8203;31295](https://redirect.github.com/nuxt/nuxt/pull/31295))
- **nuxt:** Check resolved options for polyfills
([#&#8203;31307](https://redirect.github.com/nuxt/nuxt/pull/31307))
- **nuxt:** Render style component html
([#&#8203;31337](https://redirect.github.com/nuxt/nuxt/pull/31337))
- **nuxt:** Add missing lazy hydration prop in regex
([#&#8203;31359](https://redirect.github.com/nuxt/nuxt/pull/31359))
- **nuxt:** Fully resolve nuxt dependencies
([#&#8203;31436](https://redirect.github.com/nuxt/nuxt/pull/31436))
- **vite:** Don't show interim vite build output files
([#&#8203;31439](https://redirect.github.com/nuxt/nuxt/pull/31439))
- **nuxt:** Ignore prerendering unprefixed public assets
([151912ec3](https://redirect.github.com/nuxt/nuxt/commit/151912ec3))
- **nuxt:** Use more performant router catchall pattern
([#&#8203;31450](https://redirect.github.com/nuxt/nuxt/pull/31450))
- **nuxt:** Prevent param duplication in `typedPages` implementation
([#&#8203;31331](https://redirect.github.com/nuxt/nuxt/pull/31331))
- **nuxt:** Sort route paths before creating route tree
([#&#8203;31454](https://redirect.github.com/nuxt/nuxt/pull/31454))

##### 📖 Documentation

- Update link to vercel edge network
([ec20802a5](https://redirect.github.com/nuxt/nuxt/commit/ec20802a5))
- Improve HMR performance note for Windows users
([#&#8203;31301](https://redirect.github.com/nuxt/nuxt/pull/31301))
- Correct WSL note phrasing
([#&#8203;31322](https://redirect.github.com/nuxt/nuxt/pull/31322))
- Fix typo
([#&#8203;31341](https://redirect.github.com/nuxt/nuxt/pull/31341))
- Adjust `app.head` example
([#&#8203;31350](https://redirect.github.com/nuxt/nuxt/pull/31350))
- Include package manager options in update script
([#&#8203;31346](https://redirect.github.com/nuxt/nuxt/pull/31346))
- Add missing comma
([#&#8203;31362](https://redirect.github.com/nuxt/nuxt/pull/31362))
- Add mention of `addServerTemplate` to modules guide
([#&#8203;31369](https://redirect.github.com/nuxt/nuxt/pull/31369))
- Add `rspack` and remove `test-utils` for monorepo guide
([#&#8203;31371](https://redirect.github.com/nuxt/nuxt/pull/31371))
- Adjust example
([#&#8203;31372](https://redirect.github.com/nuxt/nuxt/pull/31372))
- Update experimental docs
([#&#8203;31388](https://redirect.github.com/nuxt/nuxt/pull/31388))
- Use `ini` syntax block highlighting for `.env` files
([f79fabe46](https://redirect.github.com/nuxt/nuxt/commit/f79fabe46))
- Improve `useHydration` docs
([#&#8203;31427](https://redirect.github.com/nuxt/nuxt/pull/31427))
- Update broken docs links
([#&#8203;31430](https://redirect.github.com/nuxt/nuxt/pull/31430))
- Mention possibility of prerendering api routes
([#&#8203;31234](https://redirect.github.com/nuxt/nuxt/pull/31234))

##### 🏡 Chore

- Fix gitignore
([6fe9dff7e](https://redirect.github.com/nuxt/nuxt/commit/6fe9dff7e))
- Bump axios dependency in lockfile
([c3352e80b](https://redirect.github.com/nuxt/nuxt/commit/c3352e80b))
- Lint repo
([2ab20bfdc](https://redirect.github.com/nuxt/nuxt/commit/2ab20bfdc))
- Add scorecard badge
([#&#8203;31302](https://redirect.github.com/nuxt/nuxt/pull/31302))
- Dedupe
([be5d85f2b](https://redirect.github.com/nuxt/nuxt/commit/be5d85f2b))

#####  Tests

- Migrate runtime compiler test to playwright (+ add test cases)
([#&#8203;31405](https://redirect.github.com/nuxt/nuxt/pull/31405))
- Migrate spa preloader tests to playwright
([#&#8203;31273](https://redirect.github.com/nuxt/nuxt/pull/31273))
- Use `srvx` and random port for remote provider
([#&#8203;31432](https://redirect.github.com/nuxt/nuxt/pull/31432))

##### 🤖 CI

- Automate release on merge of of v3/v4
([6ae5b5fdb](https://redirect.github.com/nuxt/nuxt/commit/6ae5b5fdb))
- Fix workflow quoting
([fef39cf3c](https://redirect.github.com/nuxt/nuxt/commit/fef39cf3c))

##### ❤️ Contributors

- Daniel Roe
([@&#8203;danielroe](https://redirect.github.com/danielroe))
- Anoesj Sadraee ([@&#8203;Anoesj](https://redirect.github.com/Anoesj))
- Peter Radko ([@&#8203;Gwynerva](https://redirect.github.com/Gwynerva))
- Adam DeHaven
([@&#8203;adamdehaven](https://redirect.github.com/adamdehaven))
- Alex Liu
([@&#8203;Mini-ghost](https://redirect.github.com/Mini-ghost))
- Julien Huang
([@&#8203;huang-julien](https://redirect.github.com/huang-julien))
- Francesco Agnoletto
([@&#8203;Kornil](https://redirect.github.com/Kornil))
- Guillaume Chau ([@&#8203;Akryum](https://redirect.github.com/Akryum))
- imreegall ([@&#8203;imreegall](https://redirect.github.com/imreegall))
-   xjccc ([@&#8203;xjccc](https://redirect.github.com/xjccc))
-   Sam Blowes ([@&#8203;blowsie](https://redirect.github.com/blowsie))
-   Nimit012 ([@&#8203;Nimit012](https://redirect.github.com/Nimit012))
- Camille Coutens ([@&#8203;Kamsou](https://redirect.github.com/Kamsou))

</details>

<details>
<summary>unovue/reka-ui (reka-ui)</summary>

###
[`v2.1.1`](https://redirect.github.com/unovue/reka-ui/releases/tag/v2.1.1)

[Compare
Source](https://redirect.github.com/unovue/reka-ui/compare/v2.1.0...v2.1.1)

#####    🐞 Bug Fixes

-   **Calendar**:
- Properly calculate focus for next month when pagedNavigation is false
 -  by [@&#8203;epr3](https://redirect.github.com/epr3) in
[https://github.com/unovue/reka-ui/issues/1742](https://redirect.github.com/unovue/reka-ui/issues/1742)
[<samp>(7b91b)</samp>](https://redirect.github.com/unovue/reka-ui/commit/7b91bc08)
- Handle number of months > 2  -  by
[@&#8203;epr3](https://redirect.github.com/epr3) in
[https://github.com/unovue/reka-ui/issues/1744](https://redirect.github.com/unovue/reka-ui/issues/1744)
[<samp>(71023)</samp>](https://redirect.github.com/unovue/reka-ui/commit/71023c87)
-   **Combobox**:
- InjectComboboxItemContext is incorrect  -  by
[@&#8203;g12i](https://redirect.github.com/g12i) in
[https://github.com/unovue/reka-ui/issues/1722](https://redirect.github.com/unovue/reka-ui/issues/1722)
[<samp>(1b68e)</samp>](https://redirect.github.com/unovue/reka-ui/commit/1b68e5b5)
-   **HoverCard**:
- Default open type  -  by
[@&#8203;zernonia](https://redirect.github.com/zernonia) in
[https://github.com/unovue/reka-ui/issues/1732](https://redirect.github.com/unovue/reka-ui/issues/1732)
[<samp>(16ffc)</samp>](https://redirect.github.com/unovue/reka-ui/commit/16ffcc27)
-   **NavigationMenu**:
- Wrong instance of activetrigger being reference  -  by
[@&#8203;zernonia](https://redirect.github.com/zernonia) in
[https://github.com/unovue/reka-ui/issues/1741](https://redirect.github.com/unovue/reka-ui/issues/1741)
[<samp>(b72a9)</samp>](https://redirect.github.com/unovue/reka-ui/commit/b72a90b2)
-   **RangeCalendar**:
- Programatically set value doesn't update the calendar  -  by
[@&#8203;zernonia](https://redirect.github.com/zernonia) in
[https://github.com/unovue/reka-ui/issues/1739](https://redirect.github.com/unovue/reka-ui/issues/1739)
[<samp>(80001)</samp>](https://redirect.github.com/unovue/reka-ui/commit/80001892)
-   **Select**:
- Position issue for value missing in content  -  by
[@&#8203;zernonia](https://redirect.github.com/zernonia) in
[https://github.com/unovue/reka-ui/issues/1745](https://redirect.github.com/unovue/reka-ui/issues/1745)
[<samp>(770c2)</samp>](https://redirect.github.com/unovue/reka-ui/commit/770c292a)
-   **Slider**:
- Thumb has incorrect tag by default  -  by
[@&#8203;zernonia](https://redirect.github.com/zernonia) in
[https://github.com/unovue/reka-ui/issues/1734](https://redirect.github.com/unovue/reka-ui/issues/1734)
[<samp>(f8ebc)</samp>](https://redirect.github.com/unovue/reka-ui/commit/f8ebc9ec)
-   **TagsInput**:
- Fix comparing model values  -  by
[@&#8203;g12i](https://redirect.github.com/g12i) in
[https://github.com/unovue/reka-ui/issues/1723](https://redirect.github.com/unovue/reka-ui/issues/1723)
[<samp>(5dfb7)</samp>](https://redirect.github.com/unovue/reka-ui/commit/5dfb70c3)
-   **Toast**:
- Add missing swipeMove, swipeCancel, and swipeEnd events  -  by
[@&#8203;hartbit](https://redirect.github.com/hartbit) in
[https://github.com/unovue/reka-ui/

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-25 09:29:31 -04:00
renovate[bot]
8f78b3f1ca fix(deps): update dependency marked to v15 (#1249)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [marked](https://marked.js.org)
([source](https://redirect.github.com/markedjs/marked)) | [`^12.0.2` ->
`^15.0.0`](https://renovatebot.com/diffs/npm/marked/12.0.2/15.0.7) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/marked/15.0.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/marked/15.0.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/marked/12.0.2/15.0.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/marked/12.0.2/15.0.7?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>markedjs/marked (marked)</summary>

###
[`v15.0.7`](https://redirect.github.com/markedjs/marked/releases/tag/v15.0.7)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v15.0.6...v15.0.7)

##### Bug Fixes

- fix table rendered as heading
([#&#8203;3612](https://redirect.github.com/markedjs/marked/issues/3612))
([9ae87de](9ae87de7cb))

###
[`v15.0.6`](https://redirect.github.com/markedjs/marked/releases/tag/v15.0.6)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v15.0.5...v15.0.6)

##### Bug Fixes

- fix strikethrough inside strong and em to follow gfm
([#&#8203;3577](https://redirect.github.com/markedjs/marked/issues/3577))
([7712a53](7712a5324f))

###
[`v15.0.5`](https://redirect.github.com/markedjs/marked/releases/tag/v15.0.5)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v15.0.4...v15.0.5)

##### Bug Fixes

- allow strikethrough inside strong and em to follow gfm
([#&#8203;3569](https://redirect.github.com/markedjs/marked/issues/3569))
([8a01658](8a01658cac))

###
[`v15.0.4`](https://redirect.github.com/markedjs/marked/releases/tag/v15.0.4)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v15.0.3...v15.0.4)

##### Bug Fixes

- fix list with no items looping forever
([#&#8203;3560](https://redirect.github.com/markedjs/marked/issues/3560))
([e4198ed](e4198ed70d))

###
[`v15.0.3`](https://redirect.github.com/markedjs/marked/releases/tag/v15.0.3)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v15.0.2...v15.0.3)

##### Bug Fixes

- update punctuation regex syntax to fix babel mistaken transpile
([#&#8203;3547](https://redirect.github.com/markedjs/marked/issues/3547))
([9b988c4](9b988c47bd))

###
[`v15.0.2`](https://redirect.github.com/markedjs/marked/releases/tag/v15.0.2)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v15.0.1...v15.0.2)

##### Bug Fixes

- update punctuation regex syntax for compatibility
([#&#8203;3540](https://redirect.github.com/markedjs/marked/issues/3540))
([fd015f1](fd015f147d))

###
[`v15.0.1`](https://redirect.github.com/markedjs/marked/releases/tag/v15.0.1)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v15.0.0...v15.0.1)

##### Bug Fixes

- Remove unused plus typescript tightening
([#&#8203;3527](https://redirect.github.com/markedjs/marked/issues/3527))
([1f579f7](1f579f7628))

###
[`v15.0.0`](https://redirect.github.com/markedjs/marked/releases/tag/v15.0.0)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v14.1.4...v15.0.0)

##### Bug Fixes

- escape html in renderer
([#&#8203;3495](https://redirect.github.com/markedjs/marked/issues/3495))
([58d66e5](58d66e59d1))
- Move all regexps to rules
([#&#8203;3519](https://redirect.github.com/markedjs/marked/issues/3519))
([1f88deb](1f88deb58a))

##### BREAKING CHANGES

-   escape html in renderers instead of tokenizers for all tokens.

###
[`v14.1.4`](https://redirect.github.com/markedjs/marked/releases/tag/v14.1.4)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v14.1.3...v14.1.4)

##### Bug Fixes

- fix del with escaped tilde
([#&#8203;3517](https://redirect.github.com/markedjs/marked/issues/3517))
([0afe87d](0afe87d7fb))
- fix html comment after list
([#&#8203;3518](https://redirect.github.com/markedjs/marked/issues/3518))
([a612576](a612576ff6))

###
[`v14.1.3`](https://redirect.github.com/markedjs/marked/releases/tag/v14.1.3)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v14.1.2...v14.1.3)

##### Bug Fixes

- include single nested parens in emStrong link mask
([#&#8203;3475](https://redirect.github.com/markedjs/marked/issues/3475))
([2b7efa8](2b7efa8dda))
- kill SIGINT signal at man for marked --help
([#&#8203;3483](https://redirect.github.com/markedjs/marked/issues/3483))
([b1fd3ea](b1fd3eafd8))

###
[`v14.1.2`](https://redirect.github.com/markedjs/marked/releases/tag/v14.1.2)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v14.1.1...v14.1.2)

##### Bug Fixes

- fix html following list
([#&#8203;3444](https://redirect.github.com/markedjs/marked/issues/3444))
([9d7b728](9d7b728749))

###
[`v14.1.1`](https://redirect.github.com/markedjs/marked/releases/tag/v14.1.1)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v14.1.0...v14.1.1)

##### Bug Fixes

- Don't replace tabs with spaces
([#&#8203;3438](https://redirect.github.com/markedjs/marked/issues/3438))
([9ed6456](9ed6456a37))

###
[`v14.1.0`](https://redirect.github.com/markedjs/marked/releases/tag/v14.1.0)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v14.0.0...v14.1.0)

##### Bug Fixes

- don't export block or inline
([#&#8203;3427](https://redirect.github.com/markedjs/marked/issues/3427))
([3f0430a](3f0430a45e))

##### Features

- add provideLexer and provideParser hooks
([#&#8203;3424](https://redirect.github.com/markedjs/marked/issues/3424))
([447f5af](447f5af7e4))

###
[`v14.0.0`](https://redirect.github.com/markedjs/marked/releases/tag/v14.0.0)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v13.0.3...v14.0.0)

##### Bug Fixes

- allow async option to dictate type returned
([#&#8203;3341](https://redirect.github.com/markedjs/marked/issues/3341))
([b5a5004](b5a50041ae))
- Remove useNewRenderer
([#&#8203;3342](https://redirect.github.com/markedjs/marked/issues/3342))
([e64f226](e64f226539))

##### BREAKING CHANGES

-   Remove old renderer
- throw an error if `async: false` is set when an extension sets `async:
true`

###
[`v13.0.3`](https://redirect.github.com/markedjs/marked/releases/tag/v13.0.3)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v13.0.2...v13.0.3)

##### Bug Fixes

- fix recursion-like stack overflow error caused by the old render…
([#&#8203;3380](https://redirect.github.com/markedjs/marked/issues/3380))
([89af0b8](89af0b85b1))

###
[`v13.0.2`](https://redirect.github.com/markedjs/marked/releases/tag/v13.0.2)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v13.0.1...v13.0.2)

##### Bug Fixes

- fix list item with blank first line
([#&#8203;3351](https://redirect.github.com/markedjs/marked/issues/3351))
([d28e4c6](d28e4c65ea))

###
[`v13.0.1`](https://redirect.github.com/markedjs/marked/releases/tag/v13.0.1)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v13.0.0...v13.0.1)

##### Bug Fixes

- fix this type in extension methods
([#&#8203;3339](https://redirect.github.com/markedjs/marked/issues/3339))
([520b9ad](520b9ad355))

###
[`v13.0.0`](https://redirect.github.com/markedjs/marked/releases/tag/v13.0.0)

[Compare
Source](https://redirect.github.com/markedjs/marked/compare/v12.0.2...v13.0.0)

##### Bug Fixes

- Fix blockquote code continuation
([#&#8203;3264](https://redirect.github.com/markedjs/marked/issues/3264))
([7ab8185](7ab818502e))
- Add parser as a property on the Renderer object
([#&#8203;3291](https://redirect.github.com/markedjs/marked/issues/3291))
- Send block text tokens to the text renderer
([#&#8203;3291](https://redirect.github.com/markedjs/marked/issues/3291))

##### Features

- Send token objects to renderers
([#&#8203;3291](https://redirect.github.com/markedjs/marked/issues/3291))
([1ce59ea](1ce59ea827))
- Add space renderer that returns empty string by default
([#&#8203;3291](https://redirect.github.com/markedjs/marked/issues/3291))
- Add header and align properties to TableCell token
([#&#8203;3291](https://redirect.github.com/markedjs/marked/issues/3291))
- Add TableRow token
([#&#8203;3291](https://redirect.github.com/markedjs/marked/issues/3291))
- Add Checkbox token
([#&#8203;3291](https://redirect.github.com/markedjs/marked/issues/3291))

##### BREAKING CHANGES

- Add space token after blockquote and hr if there are multiple newlines
- Send token objects to renderers and move logic to parse tokens from
the parser to the renderers.
- Most extensions that update marked renderers should still work with
this version but will break in a future major version.
- Extensions that change marked renderers will need to be updated and
use new option `useNewRenderer` and accept a token object instead of
multiple parameters. See updated [Renderer
docs](https://marked.js.org/using_pro#renderer)

        ```js
        // v12 renderer extension

        const extension = {
          renderer: {
            heading(text, level) {
              // increase level by 1
              return `<h${level + 1}>${text}</h${level + 1}>`;
            }
          }
        };

        marked.use(extension);
        ```

        ```js
        // v13 renderer extension

        const extension = {
          useNewRenderer: true,
          renderer: {
            heading(token) {
              // increase depth by 1
              const text = this.parser.parseInline(token.tokens);
              const level = token.depth;
              return `<h${level + 1}>${text}</h${level + 1}>`;
            }
          }
        };

        marked.use(extension);
        ```

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

---------

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
Co-authored-by: Eli Bosley <ekbosley@gmail.com>
2025-03-25 09:29:09 -04:00
Michael Datelle
a1d02b486a refactor: swap out dropdown with reka components (#1245)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Introduced a new `DropdownMenu` component in user profiles with
dynamic content rendering.
- Added a new `Popover` component with interactive Storybook demos,
improving component discoverability.
- Added a new `DropdownMenuArrow` component to enhance dropdown visuals.
- Implemented new CSS custom properties for charts, enhancing styling
capabilities in light and dark themes.
- Enhanced dropdown functionality by encapsulating dropdown logic in a
new `UpcDropdownMenu` component.
- Added a new `Select` component for improved user interaction within
the `Sheet` component.
- Introduced a new `SheetWithSelect` story to showcase selection
functionality within the `Sheet` component.
- Updated the `Sidebar` component to improve modal behavior and content
positioning.
- Enhanced `UserProfile` components with a new feedback function for
better status indication.

- **Style**
- Refined layouts by replacing fixed widths with flexible, responsive
designs.
- Updated global styling with a refreshed chart color palette and
expanded dark mode support.

- **Refactor**
- Migrated components to use a unified UI library, streamlining
interactions and boosting consistency.
- Improved type safety in `BrandLoading` component by utilizing a new
type for variants and sizes.
- Updated component imports and organization to enhance maintainability.

- **Bug Fixes**
- Removed unused promotional code and components, simplifying the
codebase and improving performance.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: mdatelle <mike@datelle.net>
Co-authored-by: Zack Spear <hi@zackspear.com>
Co-authored-by: Eli Bosley <ekbosley@gmail.com>
2025-03-24 17:24:52 -04:00
Eli Bosley
cc85fba207 fix: update configValid state to ineligible in var.ini and adjust rel… (#1268)
…ated tests

- Changed `configValid` value from "yes" to "ineligible" in `var.ini`.
- Updated tests in `emhttp.test.ts` and `var.test.ts` to reflect the new
state.
- Refactored `var.ts` to handle the new `configErrorState` logic based
on `configValid`.
- Adjusted `config.resolver.ts` to return the correct error state.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Enhanced configuration status reporting to indicate when settings are
ineligible, improving clarity on configuration validity.

- **Chores**
  - Updated recorded download times to maintain accurate logging.
- Refined the installation process with streamlined dependency linkage
and improved script readability.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: Zack Spear <hi@zackspear.com>
2025-03-24 14:19:30 -04:00
Eli Bosley
5958d33fce chore: cleanup the cleanup scripts (#1266)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Updated the plugin installation endpoint to use a new port for
improved connectivity.
- Streamlined installation and removal processes for a more reliable
setup and clearer cleanup feedback.
- Introduced a new script to manage cleanup operations, enhancing system
maintenance during removals.
- **Chores**
- Expanded file monitoring to support additional file types, ensuring
timely updates.
- Optimized background operations that configure essential components
for enhanced overall performance.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---------

Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
2025-03-24 12:35:25 -04:00
Zack Spear
3a20930ead feat: UnraidCheckExec for Check OS Updates via UPC dropdown (#1265)
- Added `UnraidCheckExec.php` to separate concerns between UnraidCheck
and ReplaceKey, allowing for JSON responses.
- Updated `unraidcheck` script to parse query strings for compatibility
with the new class.
- Modified `webgui.ts` to call `UnraidCheckExec.php` instead of
`UnraidCheck.php` for update checks.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Updated the plugin installation process to ensure critical files
remain protected during updates.
- Introduced a dedicated update check component that now returns results
in a JSON format.
- Enhanced the web interface’s update check functionality with
streamlined request parameters.

- **Refactor**
- Separated update checking responsibilities for improved logic clarity
and overall reliability.
- Updated the interface for the update check payload to enhance
parameter handling.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-03-21 14:05:17 -07:00
Eli Bosley
bf81a63f8e chore: ensure files are uploaded with proper content encoding (#1254) 2025-03-21 10:28:33 -04:00
Zack Spear
7e6be67f61 feat: add ReplaceKey functionality to plugin (#1264)
This change enhances the plugin's capability to manage license keys
effectively.

- Introduced `ReplaceKey.php` from the webgui repo for handling
auto-extended key check & installation
- Updated dynamix.unraid.net.plg to include the new ReplaceKey.php in
restore and preserve files.
- Changed the `check()` method call in `Registration.page` to use the
`force` parameter per
https://app.asana.com/0/1204220153625175/1209573221367693/f
- Moved the `require_once` for `reboot-details.php` in Downgrade.page
and Update.page to ensure it's included after the `ReplaceKey` check.

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Enhanced license key management now validates and updates credentials
more reliably.
- Essential configuration files are preserved throughout updates and
uninstalls to maintain system integrity.

- **Chores**
- Optimized the update and registration workflows for a smoother, more
stable user experience.
- Adjusted internal processing steps to prepare for upcoming
improvements in update checks.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-03-20 14:29:55 -07:00
Zack Spear
6a92f61f1a feat: downgrade page replace key check (#1263)
Joins Update.page and Registration.page in having Replace Key check due
to relation between OS Version & License OS Eligibility

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Introduced an enhanced system validation step during initialization
that verifies key functionality before processing reboot details,
improving system reliability.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-03-20 14:08:49 -07:00
renovate[bot]
9cad1a9454 fix(deps): update dependency graphql-ws to v6 (#1210)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [graphql-ws](https://the-guild.dev/graphql/ws)
([source](https://redirect.github.com/enisdenjo/graphql-ws)) |
[`^5.16.0` ->
`^6.0.0`](https://renovatebot.com/diffs/npm/graphql-ws/5.16.2/6.0.4) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/graphql-ws/6.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/graphql-ws/6.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/graphql-ws/5.16.2/6.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/graphql-ws/5.16.2/6.0.4?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>enisdenjo/graphql-ws (graphql-ws)</summary>

###
[`v6.0.4`](https://redirect.github.com/enisdenjo/graphql-ws/blob/HEAD/CHANGELOG.md#604)

[Compare
Source](https://redirect.github.com/enisdenjo/graphql-ws/compare/v6.0.3...v6.0.4)

##### Patch Changes

-
[#&#8203;625](https://redirect.github.com/enisdenjo/graphql-ws/pull/625)
[`b4a656d`](b4a656d585)
Thanks [@&#8203;HermanBilous](https://redirect.github.com/HermanBilous)!
- Use Math.pow for retry delay calculation

###
[`v6.0.3`](https://redirect.github.com/enisdenjo/graphql-ws/blob/HEAD/CHANGELOG.md#603)

[Compare
Source](https://redirect.github.com/enisdenjo/graphql-ws/compare/v6.0.2...v6.0.3)

##### Patch Changes

-
[`747c01c`](747c01c73e)
Thanks [@&#8203;enisdenjo](https://redirect.github.com/enisdenjo)! -
Drop `ExecutionPatchResult` and `FormattedExecutionPatchResult` types

Neither of the types are officially supported (yet) and the future
versions of graphql-js adding support for stream/defer will a different
signature for the incremental execution result.

###
[`v6.0.2`](https://redirect.github.com/enisdenjo/graphql-ws/blob/HEAD/CHANGELOG.md#602)

[Compare
Source](https://redirect.github.com/enisdenjo/graphql-ws/compare/v6.0.1...v6.0.2)

##### Patch Changes

-
[#&#8203;621](https://redirect.github.com/enisdenjo/graphql-ws/pull/621)
[`6b180e8`](6b180e8fc2)
Thanks [@&#8203;pleunv](https://redirect.github.com/pleunv)! -
FormattedExecutionResult errors field returns GraphQLFormattedError

###
[`v6.0.1`](https://redirect.github.com/enisdenjo/graphql-ws/blob/HEAD/CHANGELOG.md#601)

[Compare
Source](https://redirect.github.com/enisdenjo/graphql-ws/compare/v6.0.0...v6.0.1)

##### Patch Changes

-
[#&#8203;618](https://redirect.github.com/enisdenjo/graphql-ws/pull/618)
[`6be34c7`](6be34c7969)
Thanks [@&#8203;enisdenjo](https://redirect.github.com/enisdenjo)! -
Remove exports for CommonJS for Deno exports in package.json

[Deno supports ECMAScript modules
exclusively.](https://docs.deno.com/runtime/fundamentals/modules/)

-
[#&#8203;618](https://redirect.github.com/enisdenjo/graphql-ws/pull/618)
[`6be34c7`](6be34c7969)
Thanks [@&#8203;enisdenjo](https://redirect.github.com/enisdenjo)! -
Define exports for CommonJS TypeScript definitions in package.json

###
[`v6.0.0`](https://redirect.github.com/enisdenjo/graphql-ws/blob/HEAD/CHANGELOG.md#600)

[Compare
Source](https://redirect.github.com/enisdenjo/graphql-ws/compare/v5.16.2...v6.0.0)

##### Major Changes

-
[`b668b30`](b668b304a8)
Thanks [@&#8203;enisdenjo](https://redirect.github.com/enisdenjo)! -
[@&#8203;fastify/websocket](https://redirect.github.com/fastify/websocket)
WebSocket in the context extra has been renamed from `connection` to
`socket`

##### Migrating from v5 to v6

```diff
import { makeHandler } from 'graphql-ws/use/@&#8203;fastify/websocket';

makeHandler({
  schema(ctx) {
-   const websocket = ctx.connection;
+   const websocket = ctx.socket;
  },
  context(ctx) {
-   const websocket = ctx.connection;
+   const websocket = ctx.socket;
  },
  onConnect(ctx) {
-   const websocket = ctx.connection;
+   const websocket = ctx.socket;
  },
  onDisconnect(ctx) {
-   const websocket = ctx.connection;
+   const websocket = ctx.socket;
  },
  onClose(ctx) {
-   const websocket = ctx.connection;
+   const websocket = ctx.socket;
  },
  onSubscribe(ctx) {
-   const websocket = ctx.connection;
+   const websocket = ctx.socket;
  },
  onOperation(ctx) {
-   const websocket = ctx.connection;
+   const websocket = ctx.socket;
  },
  onError(ctx) {
-   const websocket = ctx.connection;
+   const websocket = ctx.socket;
  },
  onNext(ctx) {
-   const websocket = ctx.connection;
+   const websocket = ctx.socket;
  },
  onComplete(ctx) {
-   const websocket = ctx.connection;
+   const websocket = ctx.socket;
  },
});
```

-
[#&#8203;613](https://redirect.github.com/enisdenjo/graphql-ws/pull/613)
[`3f11aba`](3f11aba495)
Thanks [@&#8203;enisdenjo](https://redirect.github.com/enisdenjo)! -
Drop support for `ws` v7

    `ws` v7 has been deprecated. Please upgrade and use v8.

-
[#&#8203;613](https://redirect.github.com/enisdenjo/graphql-ws/pull/613)
[`3f11aba`](3f11aba495)
Thanks [@&#8203;enisdenjo](https://redirect.github.com/enisdenjo)! -
Drop support for deprecated `fastify-websocket`

[`fastify-websocket` has been deprecated since
v4.3.0.](https://www.npmjs.com/package/fastify-websocket). Please
upgrade and use
[`@fastify/websocket`](https://redirect.github.com/fastify/fastify-websocket).

-
[#&#8203;613](https://redirect.github.com/enisdenjo/graphql-ws/pull/613)
[`3f11aba`](3f11aba495)
Thanks [@&#8203;enisdenjo](https://redirect.github.com/enisdenjo)! - The
`/lib/` part from imports has been removed, for example
`graphql-ws/lib/use/ws` becomes `graphql-ws/use/ws`

##### Migrating from v5 to v6

Simply remove the `/lib/` part from your graphql-ws imports that use a
handler.

##### ws

```diff
- import { useServer } from 'graphql-ws/lib/use/ws';
+ import { useServer } from 'graphql-ws/use/ws';
```

##### uWebSockets.js

```diff
- import { makeBehavior } from 'graphql-ws/lib/use/uWebSockets';
+ import { makeBehavior } from 'graphql-ws/use/uWebSockets';
```

#####
[@&#8203;fastify/websocket](https://redirect.github.com/fastify/websocket)

```diff
- import { makeHandler } from 'graphql-ws/lib/use/@&#8203;fastify/websocket';
+ import { makeHandler } from 'graphql-ws/use/@&#8203;fastify/websocket';
```

##### Bun

```diff
- import { handleProtocols, makeHandler } from 'graphql-ws/lib/use/bun';
+ import { handleProtocols, makeHandler } from 'graphql-ws/use/bun';
```

##### Deno

```diff
- import { makeHandler } from 'https://esm.sh/graphql-ws/lib/use/deno';
+ import { makeHandler } from 'https://esm.sh/graphql-ws/use/deno';
```

-
[#&#8203;613](https://redirect.github.com/enisdenjo/graphql-ws/pull/613)
[`3f11aba`](3f11aba495)
Thanks [@&#8203;enisdenjo](https://redirect.github.com/enisdenjo)! -
`ErrorMessage` uses and `onError` returns `GraphQLFormattedError`
(instead of `GraphQLError`)

Thanks [@&#8203;benjie](https://redirect.github.com/benjie) for working
on this in
[#&#8203;599](https://redirect.github.com/enisdenjo/graphql-ws/issues/599)

-
[#&#8203;613](https://redirect.github.com/enisdenjo/graphql-ws/pull/613)
[`3f11aba`](3f11aba495)
Thanks [@&#8203;enisdenjo](https://redirect.github.com/enisdenjo)! -
Least supported Node version is v20

Node v10 has been deprecated for years now. There is no reason to
support it. Bumping the engine to the current LTS (v20) also allows the
code to be leaner and use less polyfills.

-
[#&#8203;613](https://redirect.github.com/enisdenjo/graphql-ws/pull/613)
[`3f11aba`](3f11aba495)
Thanks [@&#8203;enisdenjo](https://redirect.github.com/enisdenjo)! -
Least supported `graphql` peer dependency is ^15.10.1 and ^16

Users are advised to use the latest of `graphql` because of various
improvements in performance and security.

-
[#&#8203;613](https://redirect.github.com/enisdenjo/graphql-ws/pull/613)
[`3f11aba`](3f11aba495)
Thanks [@&#8203;enisdenjo](https://redirect.github.com/enisdenjo)! -
`NextMessage` uses and `onNext` returns `FormattedExecutionResult`
(instead of `ExecutionResult`)

-
[#&#8203;613](https://redirect.github.com/enisdenjo/graphql-ws/pull/613)
[`3f11aba`](3f11aba495)
Thanks [@&#8203;enisdenjo](https://redirect.github.com/enisdenjo)! -
`schema`, `context`, `onSubscribe`, `onOperation`, `onError`, `onNext`
and `onComplete` hooks don't have the full accompanying message anymore,
only the ID and the relevant part from the message

There is really no need to pass the full `SubscribeMessage` to the
`onSubscribe` hook. The only relevant parts from the message are the
`id` and the `payload`, the `type` is useless since the hook inherently
has it (`onNext` is `next` type, `onError` is `error` type, etc).

The actual techincal reason for not having the full message is to avoid
serialising results and errors twice. Both `onNext` and `onError` allow
the user to augment the result and return it to be used instead.
`onNext` originally had the `NextMessage` argument which already has the
`FormattedExecutionResult`, and `onError` originally had the
`ErrorMessage` argument which already has the `GraphQLFormattedError`,
and they both also returned `FormattedExecutionResult` and
`GraphQLFormattedError` respectivelly - meaning, if the user serialised
the results - the serialisation would happen **twice**.

Additionally, the `onOperation`, `onError`, `onNext` and `onComplete`
now have the `payload` which is the `SubscribeMessage.payload`
(`SubscribePayload`) for easier access to the original query as well as
execution params extensions.

##### Migrating from v5 to v6

##### `schema`

```diff
import { ExecutionArgs } from 'graphql';
import { ServerOptions, SubscribePayload } from 'graphql-ws';

const opts: ServerOptions = {
- schema(ctx, message, argsWithoutSchema: Omit<ExecutionArgs, 'schema'>) {
-   const messageId = message.id;
-   const messagePayload: SubscribePayload = message.payload;
- },
+ schema(ctx, id, payload) {
+   const messageId = id;
+   const messagePayload: SubscribePayload = payload;
+ },
};
```

##### `context`

```diff
import { ExecutionArgs } from 'graphql';
import { ServerOptions, SubscribePayload } from 'graphql-ws';

const opts: ServerOptions = {
- context(ctx, message, args: ExecutionArgs) {
-   const messageId = message.id;
-   const messagePayload: SubscribePayload = message.payload;
- },
+ context(ctx, id, payload, args: ExecutionArgs) {
+   const messageId = id;
+   const messagePayload: SubscribePayload = payload;
+ },
};
```

##### `onSubscribe`

```diff
import { ServerOptions, SubscribePayload } from 'graphql-ws';

const opts: ServerOptions = {
- onSubscribe(ctx, message) {
-   const messageId = message.id;
-   const messagePayload: SubscribePayload = message.payload;
- },
+ onSubscribe(ctx, id, payload) {
+   const messageId = id;
+   const messagePayload: SubscribePayload = payload;
+ },
};
```

##### `onOperation`

The `SubscribeMessage.payload` is not useful here at all, the `payload`
has been parsed to ready-to-use graphql execution args and should be
used instead.

```diff
import { ExecutionArgs } from 'graphql';
import { ServerOptions, SubscribePayload, OperationResult } from 'graphql-ws';

const opts: ServerOptions = {
- onOperation(ctx, message, args: ExecutionArgs, result: OperationResult) {
-   const messageId = message.id;
-   const messagePayload: SubscribePayload = message.payload;
- },
+ onOperation(ctx, id, payload, args: ExecutionArgs, result: OperationResult) {
+   const messageId = id;
+   const messagePayload: SubscribePayload = payload;
+ },
};
```

##### `onError`

The `ErrorMessage.payload` (`GraphQLFormattedError[]`) is not useful
here at all, the user has access to `GraphQLError[]` that are true
instances of the error containing object references to `originalError`s
and other properties. The user can always convert and return
`GraphQLFormattedError[]` by using the `.toJSON()` method.

```diff
import { GraphQLError, GraphQLFormattedError } from 'graphql';
import { ServerOptions, SubscribePayload } from 'graphql-ws';

const opts: ServerOptions = {
- onError(ctx, message, errors) {
-   const messageId = message.id;
-   const graphqlErrors: readonly GraphQLError[] = errors;
-   const errorMessagePayload: readonly GraphQLFormattedError[] = message.payload;
- },
+ onError(ctx, id, payload, errors) {
+   const messageId = id;
+   const graphqlErrors: readonly GraphQLError[] = errors;
+   const subscribeMessagePayload: SubscribePayload = payload;
+   const errorMessagePayload: readonly GraphQLFormattedError[] = errors.map((e) => e.toJSON());
+ },
};
```

##### `onNext`

The `NextMessage.payload` (`FormattedExecutionResult`) is not useful
here at all, the user has access to `ExecutionResult` that contains
actual object references to error instances. The user can always convert
and return `FormattedExecutionResult` by serialising the errors with
`GraphQLError.toJSON()` method.

```diff
import { ExecutionArgs, ExecutionResult, FormattedExecutionResult } from 'graphql';
import { ServerOptions, SubscribePayload } from 'graphql-ws';

const opts: ServerOptions = {
- onNext(ctx, message, args: ExecutionArgs, result: ExecutionResult) {
-   const messageId = message.id;
-   const nextMessagePayload: FormattedExecutionResult = message.payload;
- },
+ onNext(ctx, id, payload, args: ExecutionArgs, result: ExecutionResult) {
+   const messageId = id;
+   const subscribeMessagePayload: SubscribePayload = payload;
+   const nextMessagePayload: FormattedExecutionResult = { ...result, errors: result.errors?.map((e) => e.toJSON()) };
+ },
};
```

##### `onComplete`

```diff
import { ServerOptions, SubscribePayload } from 'graphql-ws';

const opts: ServerOptions = {
- onComplete(ctx, message) {
-   const messageId = message.id;
- },
+ onComplete(ctx, id, payload) {
+   const messageId = id;
+   const subscribeMessagePayload: SubscribePayload = payload;
+ },
};
```

-
[#&#8203;613](https://redirect.github.com/enisdenjo/graphql-ws/pull/613)
[`3f11aba`](3f11aba495)
Thanks [@&#8203;enisdenjo](https://redirect.github.com/enisdenjo)! -
Errors thrown from subscription iterables will be caught and reported
through the `ErrorMessage`

Compared to the behaviour before, which terminated the whole WebSocket
connection - those errors are now gracefully reported and terminate only
the specific subscription that threw the error.

There's been [an editorial change in the GraphQL Spec suggesting this
being the correct
approach](https://redirect.github.com/graphql/graphql-spec/pull/1099).

Also, if you'd like to get involved and ideally drop your opinion about
whether iterable errors should be reported as errors or
`ExecutionResult`s with `errors` field set, [please read more
here](https://redirect.github.com/graphql/graphql-spec/pull/1127).

##### Migrating from v5 to v6

If you had used the suggested "ws server usage with custom subscribe
method that gracefully handles thrown errors" recipe, you can simply
remove it since this behaviour is now baked in.

```diff
import { subscribe } from 'graphql';
import { useServer } from 'graphql-ws/use/ws';
import { WebSocketServer } from 'ws'; // yarn add ws

const wsServer = new WebSocketServer({
  port: 4000,
  path: '/graphql',
});

useServer(
  {
    schema,
-   async subscribe(...args) {
-     const result = await subscribe(...args);
-     if ('next' in result) {
-       // is an async iterable, augment the next method to handle thrown errors
-       const originalNext = result.next;
-       result.next = async () => {
-         try {
-           return await originalNext();
-         } catch (err) {
-           // gracefully handle the error thrown from the next method
-           return { value: { errors: [err] } };
-         }
-       };
-     }
-     return result;
-   },
  },
  wsServer,
);
```

-
[#&#8203;613](https://redirect.github.com/enisdenjo/graphql-ws/pull/613)
[`3f11aba`](3f11aba495)
Thanks [@&#8203;enisdenjo](https://redirect.github.com/enisdenjo)! -
Remove deprecated `isMessage`, use `validateMessage` instead

##### Migrating from v5 to v6

Replace all ocurrances of `isMessage` with `validateMessage`. Note that
`validateMessage` throws if the message is not valid, compared with
`isMessage` that simply returned true/false.

```diff
- import { isMessage } from 'graphql-ws';
+ import { validateMessage } from 'graphql-ws';

function isGraphQLWSMessage(val) {
- return isMessage(val);
+ try {
+   validateMessage(val);
+   return true;
+ } catch {
+   return false;
+ }
}
```

-
[#&#8203;613](https://redirect.github.com/enisdenjo/graphql-ws/pull/613)
[`3f11aba`](3f11aba495)
Thanks [@&#8203;enisdenjo](https://redirect.github.com/enisdenjo)! -
Removed deprecated `isFatalConnectionProblem`, use `shouldRetry` instead

##### Migrating from v5 to v6

Replace all ocurrances of `isFatalConnectionProblem` with `shouldRetry`.
Note that the result is inverted, where you returned `false` in
`isFatalConnectionProblem` you should return `true` in `shouldRetry`.

```diff
import { createClient } from 'graphql-ws';

const client = createClient({
  url: 'ws://localhost:4000/graphql',
- isFatalConnectionProblem: () => false,
+ shouldRetry: () => true,
});
```

##### Minor Changes

-
[#&#8203;613](https://redirect.github.com/enisdenjo/graphql-ws/pull/613)
[`3f11aba`](3f11aba495)
Thanks [@&#8203;enisdenjo](https://redirect.github.com/enisdenjo)! -
Client is truly zero-dependency, not even a peer dependency on `graphql`

In non-browser environments, you can use only the client and not even
depend on `graphql` by importing from `graphql-ws/client`.

    ```ts
    import { createClient } from 'graphql-ws/client';

    const client = createClient({
      url: 'ws://localhost:4000/graphql',
    });
    ```

Note that, in browser envirments (and of course having your bundler use
the [`browser` package.json
field](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#browser)),
you don't have to import from `graphql-ws/client` - simply importing
from `graphql-ws` will only have the `createClient` available.

-
[#&#8203;615](https://redirect.github.com/enisdenjo/graphql-ws/pull/615)
[`29dd26a`](29dd26a509)
Thanks [@&#8203;enisdenjo](https://redirect.github.com/enisdenjo)! -
Define optional peer dependencies and least supported versions

Using the
[`peerDependencies`](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#peerdependencies)
in combination with
[`peerDependenciesMeta`](https://docs.npmjs.com/cli/v11/configuring-npm/package-json#peerdependenciesmeta)
configuration in `package.json`.

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4xNzYuMiIsInVwZGF0ZWRJblZlciI6IjM5LjE3Ni4yIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-20 15:57:04 -04:00
renovate[bot]
2c01ba9610 fix(deps): update dependency vue-i18n to v11 (#1261)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[vue-i18n](https://redirect.github.com/intlify/vue-i18n/tree/master/packages/vue-i18n#readme)
([source](https://redirect.github.com/intlify/vue-i18n/tree/HEAD/packages/vue-i18n))
| [`^10.0.5` ->
`^11.0.0`](https://renovatebot.com/diffs/npm/vue-i18n/10.0.6/11.1.2) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/vue-i18n/11.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vue-i18n/11.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vue-i18n/10.0.6/11.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vue-i18n/10.0.6/11.1.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>intlify/vue-i18n (vue-i18n)</summary>

###
[`v11.1.2`](https://redirect.github.com/intlify/vue-i18n/releases/tag/v11.1.2)

[Compare
Source](https://redirect.github.com/intlify/vue-i18n/compare/v11.1.1...v11.1.2)

<!-- Release notes generated using configuration in .github/release.yml
at v11.1.2 -->

#### What's Changed

##### 🔒 Security Fixes

- fix: prototype pollution in `handleFlatJson`, about details see
https://github.com/intlify/vue-i18n/security/advisories/GHSA-p2ph-7g93-hw3m

**Full Changelog**:
https://github.com/intlify/vue-i18n/compare/v11.1.1...v11.1.2

###
[`v11.1.1`](https://redirect.github.com/intlify/vue-i18n/releases/tag/v11.1.1)

[Compare
Source](https://redirect.github.com/intlify/vue-i18n/compare/v11.1.0...v11.1.1)

<!-- Release notes generated using configuration in .github/release.yml
at v11.1.1 -->

**Full Changelog**:
https://github.com/intlify/vue-i18n/compare/v11.1.0...v11.1.1

###
[`v11.1.0`](https://redirect.github.com/intlify/vue-i18n/releases/tag/v11.1.0)

[Compare
Source](https://redirect.github.com/intlify/vue-i18n/compare/v11.0.1...v11.1.0)

<!-- Release notes generated using configuration in .github/release.yml
at v11.1.0 -->

#### What's Changed

##### 🌟 Features

- feat: configurable `ComponentCustomProperties['$i18n']` type by
[@&#8203;BobbieGoede](https://redirect.github.com/BobbieGoede) in
[https://github.com/intlify/vue-i18n/pull/2094](https://redirect.github.com/intlify/vue-i18n/pull/2094)

##### 📝️ Documentations

- fix: vue-i18n v8 EOL by
[@&#8203;kazupon](https://redirect.github.com/kazupon) in
[https://github.com/intlify/vue-i18n/pull/2060](https://redirect.github.com/intlify/vue-i18n/pull/2060)

**Full Changelog**:
https://github.com/intlify/vue-i18n/compare/v11.0.1...v11.1.0

###
[`v11.0.1`](https://redirect.github.com/intlify/vue-i18n/blob/HEAD/CHANGELOG.md#v1101-2024-12-26T074058Z)

[Compare
Source](https://redirect.github.com/intlify/vue-i18n/compare/v11.0.0...v11.0.1)

This changelog is generated by [GitHub
Releases](https://redirect.github.com/intlify/vue-i18n/releases/tag/v11.0.1)

<!-- Release notes generated using configuration in .github/release.yml
at v11.0.1 -->

#### What's Changed

#####  Improvement Features

- fix: v-t custom directive warning when it will run by
[@&#8203;kazupon](https://redirect.github.com/kazupon) in
[https://github.com/intlify/vue-i18n/pull/2057](https://redirect.github.com/intlify/vue-i18n/pull/2057)

**Full Changelog**:
https://github.com/intlify/vue-i18n/compare/v11.0.0...v11.0.1

###
[`v11.0.0`](https://redirect.github.com/intlify/vue-i18n/blob/HEAD/CHANGELOG.md#v1100-2024-12-24T150100Z)

[Compare
Source](https://redirect.github.com/intlify/vue-i18n/compare/v10.0.6...v11.0.0)

This changelog is generated by [GitHub
Releases](https://redirect.github.com/intlify/vue-i18n/releases/tag/v11.0.0)

<!-- Release notes generated using configuration in .github/release.yml
at v11.0.0 -->

#### What's Changed

##### Deprecate Legacy API mode

The Legacy API mode was the API mode compatible with v8 for Vue 2. When
v9 was released, the Legacy API was provided to smooth the migration
from v8 to v9.

Legacy API mode will be deprecated in v11, as previous vue-i18n releases
have already provided the following to support migration to Composition
API mode

- Migration from Legacy API mode to Composition API mode, see the
[docs](https://vue-i18n.intlify.dev/guide/migration/vue3.html)
- Composition API usage, see the
[docs](https://vue-i18n.intlify.dev/guide/advanced/composition.html)

For compatibility, Legacy API mode still works in v11, but will be
removed entirely in v12, so Legacy API mode will not work after that
version.

##### Deprecate Custom Directive `v-t`

The advantage of `v-t` was that it could optimize performance using the
vue compiler transform and the pre-translation of `vue-i18n-extension`.

This feature was supported from Vue 2.
About details see the blog
[article](https://medium.com/@&#8203;kazu_pon/performance-optimization-of-vue-i18n-83099eb45c2d)

In Vue 3, due to the Composition API, the pre-translation of
[`vue-i18n-extension`](https://redirect.github.com/intlify/vue-i18n-extensions)
is now limited only for global scope.

In addition, Vue 3 Virtual DOM optimization has been introduced, and the
optimization provided by `vue-i18n-extension` is no longer very
effective. We need to require settings for SSR, the benefits of using
`v-t` have disappeared. And DX of templates using `v-t` is not good.
Custom directives do not work with key completion in editors (e.g.
vscode).

For compatibility, `v-t` mode still works in v11, but will be removed
entirely in v12, so `v-t` will not work after that version.

##### Drop `tc` and `$tc` for Legacy API mode

These APIs had already deprecated in warning about being dropped in v11.
docs
[says](https://vue-i18n.intlify.dev/guide/migration/breaking10.html#deprecate-tc-and-tc-for-legacy-api-mode)

##### Vue I18n maintenance Status

Vue I18n v8 is no longer supported after 2025. Vue I18n v9 and Vue I18n
v10 is in maintenance mode after 2025 July.

With the release of Vue I18n v11, that version will become mainstream.

The maintenance detail status of Vue I18n v9 and Vue I18n v10 is as
follows:

<img
src="https://raw.githubusercontent.com/intlify/vue-i18n/master/docs/public/lifecycle2025.svg"
/>

You can check the maintenance status on the
[docs](https://vue-i18n.intlify.dev/guide/maintenance.html)

#####  Braeking Changes

- feat!: deprecate Legacy API mode by
[@&#8203;kazupon](https://redirect.github.com/kazupon) in
[https://github.com/intlify/vue-i18n/pull/2016](https://redirect.github.com/intlify/vue-i18n/pull/2016)
- breaking: drop `$tc` and `tc` by
[@&#8203;kazupon](https://redirect.github.com/kazupon) in
[https://github.com/intlify/vue-i18n/pull/2017](https://redirect.github.com/intlify/vue-i18n/pull/2017)
- feat!: deprecate `v-t` custom directive by
[@&#8203;kazupon](https://redirect.github.com/kazupon) in
[https://github.com/intlify/vue-i18n/pull/2045](https://redirect.github.com/intlify/vue-i18n/pull/2045)

#####  Improvement Features

- fix: `tm` function should accept `DefineLocaleMessage` key type by
[@&#8203;BobbieGoede](https://redirect.github.com/BobbieGoede) in
[https://github.com/intlify/vue-i18n/pull/2014](https://redirect.github.com/intlify/vue-i18n/pull/2014)

##### 🔒 Security Fixes

- fix: security vulnerability fix porting by
[@&#8203;kazupon](https://redirect.github.com/kazupon) in
[https://github.com/intlify/vue-i18n/pull/2034](https://redirect.github.com/intlify/vue-i18n/pull/2034)

##### 📝️ Documentations

- Change config prop for quasar flags by
[@&#8203;chrissyast](https://redirect.github.com/chrissyast) in
[https://github.com/intlify/vue-i18n/pull/2003](https://redirect.github.com/intlify/vue-i18n/pull/2003)
- docs: Pluralization Page by
[@&#8203;Sammuel09](https://redirect.github.com/Sammuel09) in
[https://github.com/intlify/vue-i18n/pull/1998](https://redirect.github.com/intlify/vue-i18n/pull/1998)
- docs: fix composition section by
[@&#8203;Sammuel09](https://redirect.github.com/Sammuel09) in
[https://github.com/intlify/vue-i18n/pull/2008](https://redirect.github.com/intlify/vue-i18n/pull/2008)
- fix(docs): correct output in composition api example by
[@&#8203;pejeio](https://redirect.github.com/pejeio) in
[https://github.com/intlify/vue-i18n/pull/2012](https://redirect.github.com/intlify/vue-i18n/pull/2012)
- docs: not use deprecated api by
[@&#8203;kazupon](https://redirect.github.com/kazupon) in
[https://github.com/intlify/vue-i18n/pull/2013](https://redirect.github.com/intlify/vue-i18n/pull/2013)
- docs: fix wrong plural example by
[@&#8203;kazupon](https://redirect.github.com/kazupon) in
[https://github.com/intlify/vue-i18n/pull/2033](https://redirect.github.com/intlify/vue-i18n/pull/2033)
- docx(pluralization.md): Correct spelling from 'gloal' to 'global' by
[@&#8203;PuppyOne](https://redirect.github.com/PuppyOne) in
[https://github.com/intlify/vue-i18n/pull/2038](https://redirect.github.com/intlify/vue-i18n/pull/2038)
- Fix typo by [@&#8203;shaedrich](https://redirect.github.com/shaedrich)
in
[https://github.com/intlify/vue-i18n/pull/2040](https://redirect.github.com/intlify/vue-i18n/pull/2040)
- Fix another typo by
[@&#8203;shaedrich](https://redirect.github.com/shaedrich) in
[https://github.com/intlify/vue-i18n/pull/2041](https://redirect.github.com/intlify/vue-i18n/pull/2041)
- docs: add maintenance status by
[@&#8203;kazupon](https://redirect.github.com/kazupon) in
[https://github.com/intlify/vue-i18n/pull/2044](https://redirect.github.com/intlify/vue-i18n/pull/2044)

#### 👋 New Contributors

- [@&#8203;chrissyast](https://redirect.github.com/chrissyast) made
their first contribution in
[https://github.com/intlify/vue-i18n/pull/2003](https://redirect.github.com/intlify/vue-i18n/pull/2003)
- [@&#8203;Sammuel09](https://redirect.github.com/Sammuel09) made their
first contribution in
[https://github.com/intlify/vue-i18n/pull/1998](https://redirect.github.com/intlify/vue-i18n/pull/1998)
- [@&#8203;pejeio](https://redirect.github.com/pejeio) made their first
contribution in
[https://github.com/intlify/vue-i18n/pull/2012](https://redirect.github.com/intlify/vue-i18n/pull/2012)
- [@&#8203;PuppyOne](https://redirect.github.com/PuppyOne) made their
first contribution in
[https://github.com/intlify/vue-i18n/pull/2038](https://redirect.github.com/intlify/vue-i18n/pull/2038)
- [@&#8203;shaedrich](https://redirect.github.com/shaedrich) made their
first contribution in
[https://github.com/intlify/vue-i18n/pull/2040](https://redirect.github.com/intlify/vue-i18n/pull/2040)

**Full Changelog**:
https://github.com/intlify/vue-i18n/compare/v10.0.4...v11.0.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-20 15:56:01 -04:00
renovate[bot]
9ce10a72b2 fix(deps): update vueuse monorepo to v13 (major) (#1262)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
|
[@vueuse/components](https://redirect.github.com/vueuse/vueuse/tree/main/packages/components#readme)
([source](https://redirect.github.com/vueuse/vueuse/tree/HEAD/packages/components))
| [`^12.0.0` ->
`^13.0.0`](https://renovatebot.com/diffs/npm/@vueuse%2fcomponents/12.8.2/13.0.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@vueuse%2fcomponents/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vueuse%2fcomponents/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vueuse%2fcomponents/12.8.2/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vueuse%2fcomponents/12.8.2/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [@vueuse/core](https://redirect.github.com/vueuse/vueuse)
([source](https://redirect.github.com/vueuse/vueuse/tree/HEAD/packages/core))
| [`^12.0.0` ->
`^13.0.0`](https://renovatebot.com/diffs/npm/@vueuse%2fcore/12.8.2/13.0.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@vueuse%2fcore/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vueuse%2fcore/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vueuse%2fcore/12.8.2/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vueuse%2fcore/12.8.2/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@vueuse/integrations](https://redirect.github.com/vueuse/vueuse/tree/main/packages/integrations#readme)
([source](https://redirect.github.com/vueuse/vueuse/tree/HEAD/packages/integrations))
| [`^12.0.0` ->
`^13.0.0`](https://renovatebot.com/diffs/npm/@vueuse%2fintegrations/12.8.2/13.0.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@vueuse%2fintegrations/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vueuse%2fintegrations/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vueuse%2fintegrations/12.8.2/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vueuse%2fintegrations/12.8.2/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
|
[@vueuse/nuxt](https://redirect.github.com/vueuse/vueuse/tree/main/packages/nuxt#readme)
([source](https://redirect.github.com/vueuse/vueuse/tree/HEAD/packages/nuxt))
| [`^12.0.0` ->
`^13.0.0`](https://renovatebot.com/diffs/npm/@vueuse%2fnuxt/12.8.2/13.0.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@vueuse%2fnuxt/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@vueuse%2fnuxt/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@vueuse%2fnuxt/12.8.2/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@vueuse%2fnuxt/12.8.2/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>vueuse/vueuse (@&#8203;vueuse/components)</summary>

###
[`v13.0.0`](https://redirect.github.com/vueuse/vueuse/releases/tag/v13.0.0)

[Compare
Source](https://redirect.github.com/vueuse/vueuse/compare/v12.8.2...v13.0.0)

#####    🚨 Breaking Changes

- Drop CJS build, now it's ESM-only  -  by
[@&#8203;antfu](https://redirect.github.com/antfu) in
[https://github.com/vueuse/vueuse/issues/4581](https://redirect.github.com/vueuse/vueuse/issues/4581)
[<samp>(5e046)</samp>](https://redirect.github.com/vueuse/vueuse/commit/5e0467bf)

#####     [View changes on
GitHub](https://redirect.github.com/vueuse/vueuse/compare/v12.8.2...v13.0.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about these
updates again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-20 15:03:30 -04:00
Zack Spear
f3e6a0011e feat: ReplaceKey functionality in Registration and Update pages (#1246)
- Handles auto-extensions key check and install of extend license key
with new OS Updates Expiration date

Related to https://github.com/unraid/webgui/pull/2071 but not 100%
dependent on them.

@elibosley, do we want to use the `force` param on the `check()` method
for either of these pages?

Additionally, what do you think about any potential integration with
`UnraidCheck.php` – which is used for the UPC's "Check for Updates"
button and the user configured automatically scheduled update check?

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **New Features**
- Enhanced plugin registration and update processes with an integrated
key validation step that verifies system parameters automatically.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->

---
- To see the specific tasks where the Asana app for GitHub is being
used, see below:
  - https://app.asana.com/0/0/1209573221367688
2025-03-20 14:50:20 -04:00
renovate[bot]
cb2020dee6 fix(deps): update dependency shadcn-vue to v1 (#1259)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [shadcn-vue](https://redirect.github.com/unovue/shadcn-vue)
([source](https://redirect.github.com/unovue/shadcn-vue/tree/HEAD/packages/cli))
| [`^0.11.3` ->
`^1.0.0`](https://renovatebot.com/diffs/npm/shadcn-vue/0.11.4/1.0.3) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/shadcn-vue/1.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/shadcn-vue/1.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/shadcn-vue/0.11.4/1.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/shadcn-vue/0.11.4/1.0.3?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>unovue/shadcn-vue (shadcn-vue)</summary>

###
[`v1.0.3`](https://redirect.github.com/unovue/shadcn-vue/releases/tag/v1.0.3)

[Compare
Source](https://redirect.github.com/unovue/shadcn-vue/compare/v1.0.2...v1.0.3)

#####    🐞 Bug Fixes

- Tags input with combobox demo  -  by
[@&#8203;zernonia](https://redirect.github.com/zernonia)
[<samp>(15bd4)</samp>](https://redirect.github.com/unovue/shadcn-vue/commit/15bd4314)
- Remove type inference for default valueformmater due to upstream
compiler bug  -  by
[@&#8203;zernonia](https://redirect.github.com/zernonia)
[<samp>(098fe)</samp>](https://redirect.github.com/unovue/shadcn-vue/commit/098fe5ad)
- Transform js issue  -  by
[@&#8203;zernonia](https://redirect.github.com/zernonia)
[<samp>(b1e49)</samp>](https://redirect.github.com/unovue/shadcn-vue/commit/b1e49fe6)

#####     [View changes on
GitHub](https://redirect.github.com/unovue/shadcn-vue/compare/v1.0.2...v1.0.3)

###
[`v1.0.2`](https://redirect.github.com/unovue/shadcn-vue/releases/tag/v1.0.2)

[Compare
Source](https://redirect.github.com/unovue/shadcn-vue/compare/v1.0.1...v1.0.2)

#####    🐞 Bug Fixes

- AvatarImage to have slots  -  by
[@&#8203;zernonia](https://redirect.github.com/zernonia)
[<samp>(1c9c5)</samp>](https://redirect.github.com/unovue/shadcn-vue/commit/1c9c5445)
- Old `checked` api  -  by
[@&#8203;zernonia](https://redirect.github.com/zernonia)
[<samp>(239ff)</samp>](https://redirect.github.com/unovue/shadcn-vue/commit/239ff691)
- Js detype error when missing local reference to props  -  by
[@&#8203;zernonia](https://redirect.github.com/zernonia)
[<samp>(f00c0)</samp>](https://redirect.github.com/unovue/shadcn-vue/commit/f00c0de0)
- **Chart**: Invalid chart legend size  -  by
[@&#8203;hooray](https://redirect.github.com/hooray) and
[@&#8203;zernonia](https://redirect.github.com/zernonia) in
[https://github.com/unovue/shadcn-vue/issues/997](https://redirect.github.com/unovue/shadcn-vue/issues/997)
[<samp>(4f3e8)</samp>](https://redirect.github.com/unovue/shadcn-vue/commit/4f3e829f)
- **Demo**: Clear input field after sending message in CardChat.vue  - 
by [@&#8203;IceyWu](https://redirect.github.com/IceyWu) in
[https://github.com/unovue/shadcn-vue/issues/959](https://redirect.github.com/unovue/shadcn-vue/issues/959)
[<samp>(6aaa1)</samp>](https://redirect.github.com/unovue/shadcn-vue/commit/6aaa1dd9)
- **registry**: Button default styling  -  by
[@&#8203;zernonia](https://redirect.github.com/zernonia)
[<samp>(6a544)</samp>](https://redirect.github.com/unovue/shadcn-vue/commit/6a544f99)

#####     [View changes on
GitHub](https://redirect.github.com/unovue/shadcn-vue/compare/v1.0.1...v1.0.2)

###
[`v1.0.1`](https://redirect.github.com/unovue/shadcn-vue/releases/tag/v1.0.1)

[Compare
Source](https://redirect.github.com/unovue/shadcn-vue/compare/v1.0.0...v1.0.1)

#####    🐞 Bug Fixes

- **CLI**: Init, support js, update docs  -  by
[@&#8203;zernonia](https://redirect.github.com/zernonia) in
[https://github.com/unovue/shadcn-vue/issues/1053](https://redirect.github.com/unovue/shadcn-vue/issues/1053)
[<samp>(cdfe2)</samp>](https://redirect.github.com/unovue/shadcn-vue/commit/cdfe2e8e)

#####     [View changes on
GitHub](https://redirect.github.com/unovue/shadcn-vue/compare/v1.0.0...v1.0.1)

###
[`v1.0.0`](https://redirect.github.com/unovue/shadcn-vue/releases/tag/v1.0.0)

[Compare
Source](https://redirect.github.com/unovue/shadcn-vue/compare/v0.11.4...v1.0.0)

#####    🚀 Features

- Reka-ui & updated cli  -  by
[@&#8203;zernonia](https://redirect.github.com/zernonia) in
[https://github.com/unovue/shadcn-vue/issues/917](https://redirect.github.com/unovue/shadcn-vue/issues/917)
[<samp>(bc6da)</samp>](https://redirect.github.com/unovue/shadcn-vue/commit/bc6dae3d)

#####     [View changes on
GitHub](https://redirect.github.com/unovue/shadcn-vue/compare/v0.11.4...v1.0.0)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-20 10:29:16 -04:00
renovate[bot]
db189abec4 chore(deps): update dependency @types/pify to v6 (#1228)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| @&#8203;types/pify | [`^5.0.4` ->
`^6.0.0`](https://renovatebot.com/diffs/npm/@types%2fpify/5.0.4/6.1.0) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/@types%2fpify/6.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@types%2fpify/6.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@types%2fpify/5.0.4/6.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@types%2fpify/5.0.4/6.1.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-20 10:25:18 -04:00
renovate[bot]
d8afc8f4c9 fix(deps): update dependency pm2 to v6 (#1258)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [pm2](http://pm2.keymetrics.io/)
([source](https://redirect.github.com/Unitech/pm2)) | [`^5.4.2` ->
`^6.0.0`](https://renovatebot.com/diffs/npm/pm2/5.4.3/6.0.5) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/pm2/6.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/pm2/6.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/pm2/5.4.3/6.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/pm2/5.4.3/6.0.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>Unitech/pm2 (pm2)</summary>

###
[`v6.0.5`](https://redirect.github.com/Unitech/pm2/blob/HEAD/CHANGELOG.md#605)

[Compare
Source](5e20239d63...v6.0.5)

- Bun support - Fixes
[#&#8203;5893](https://redirect.github.com/Unitech/pm2/issues/5893)
[#&#8203;5774](https://redirect.github.com/Unitech/pm2/issues/5774)
[#&#8203;5682](https://redirect.github.com/Unitech/pm2/issues/5682)
[#&#8203;5675](https://redirect.github.com/Unitech/pm2/issues/5675)
[#&#8203;5777](https://redirect.github.com/Unitech/pm2/issues/5777)
- Disable git parsing by default
[#&#8203;5909](https://redirect.github.com/Unitech/pm2/issues/5909)
[#&#8203;2182](https://redirect.github.com/Unitech/pm2/issues/2182)
[#&#8203;5801](https://redirect.github.com/Unitech/pm2/issues/5801)
[#&#8203;5051](https://redirect.github.com/Unitech/pm2/issues/5051)
[#&#8203;5696](https://redirect.github.com/Unitech/pm2/issues/5696)
- Add WEBP content type for pm2 serve
[#&#8203;5900](https://redirect.github.com/Unitech/pm2/issues/5900)
[@&#8203;tbo47](https://redirect.github.com/tbo47)
- Enable PM2 module update from tarball
[#&#8203;5906](https://redirect.github.com/Unitech/pm2/issues/5906)
[@&#8203;AYOKINYA](https://redirect.github.com/AYOKINYA)
- Fix treekil on FreeBSD
[#&#8203;5896](https://redirect.github.com/Unitech/pm2/issues/5896)
[@&#8203;skeyby](https://redirect.github.com/skeyby)
- fix allowing to update namespaced pm2 NPM module
([@&#8203;org/module-name](https://redirect.github.com/org/module-name))
[#&#8203;5915](https://redirect.github.com/Unitech/pm2/issues/5915)
[@&#8203;endelendel](https://redirect.github.com/endelendel)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-20 10:25:06 -04:00
Pujit Mehrotra
3bfcc8e8c0 fix: node installation not persisting across reboots (#1256)
thank you to SteveHawk on the unraid.net forums for surfacing this:
https://forums.unraid.net/topic/188319-persist-node-package-download/

<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->

## Summary by CodeRabbit

- **Bug Fixes**
- Improved the plugin’s file-cleanup process by correcting the reference
used to identify outdated Node.js archive files. This update ensures
that file management functions as intended, contributing to more
reliable plugin behavior.

<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-03-20 10:18:40 -04:00
renovate[bot]
1892e23c22 fix(deps): update dependency pino-pretty to v13 (#1250)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [pino-pretty](https://redirect.github.com/pinojs/pino-pretty) |
[`^11.3.0` ->
`^13.0.0`](https://renovatebot.com/diffs/npm/pino-pretty/11.3.0/13.0.0)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/pino-pretty/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/pino-pretty/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/pino-pretty/11.3.0/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/pino-pretty/11.3.0/13.0.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>pinojs/pino-pretty (pino-pretty)</summary>

###
[`v13.0.0`](https://redirect.github.com/pinojs/pino-pretty/releases/tag/v13.0.0)

[Compare
Source](https://redirect.github.com/pinojs/pino-pretty/compare/v12.1.0...v13.0.0)

#### What's Changed

- chore: replace readable-stream with built-in stream by
[@&#8203;benmccann](https://redirect.github.com/benmccann) in
[https://github.com/pinojs/pino-pretty/pull/542](https://redirect.github.com/pinojs/pino-pretty/pull/542)

#### New Contributors

- [@&#8203;benmccann](https://redirect.github.com/benmccann) made their
first contribution in
[https://github.com/pinojs/pino-pretty/pull/542](https://redirect.github.com/pinojs/pino-pretty/pull/542)

**Full Changelog**:
https://github.com/pinojs/pino-pretty/compare/v12.1.0...v13.0.0

###
[`v12.1.0`](https://redirect.github.com/pinojs/pino-pretty/releases/tag/v12.1.0)

[Compare
Source](https://redirect.github.com/pinojs/pino-pretty/compare/v12.0.0...v12.1.0)

#### What's Changed

- fix: unescape \ for levelKey by
[@&#8203;eliw00d](https://redirect.github.com/eliw00d) in
[https://github.com/pinojs/pino-pretty/pull/538](https://redirect.github.com/pinojs/pino-pretty/pull/538)

**Full Changelog**:
https://github.com/pinojs/pino-pretty/compare/v12.0.0...v12.1.0

###
[`v12.0.0`](https://redirect.github.com/pinojs/pino-pretty/releases/tag/v12.0.0)

[Compare
Source](https://redirect.github.com/pinojs/pino-pretty/compare/v11.3.0...v12.0.0)

#### What's Changed

- build(deps-dev): lock typescript minor version by
[@&#8203;Fdawgs](https://redirect.github.com/Fdawgs) in
[https://github.com/pinojs/pino-pretty/pull/534](https://redirect.github.com/pinojs/pino-pretty/pull/534)
- Bump typescript from 5.0.4 to 5.6.3 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/pinojs/pino-pretty/pull/535](https://redirect.github.com/pinojs/pino-pretty/pull/535)
- Drop support for Node.js 14 & 16 by
[@&#8203;eliw00d](https://redirect.github.com/eliw00d) in
[https://github.com/pinojs/pino-pretty/pull/540](https://redirect.github.com/pinojs/pino-pretty/pull/540)

#### New Contributors

- [@&#8203;eliw00d](https://redirect.github.com/eliw00d) made their
first contribution in
[https://github.com/pinojs/pino-pretty/pull/540](https://redirect.github.com/pinojs/pino-pretty/pull/540)

**Full Changelog**:
https://github.com/pinojs/pino-pretty/compare/v11.3.0...v12.0.0

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-19 22:18:44 -04:00
renovate[bot]
03ece335b8 fix(deps): update dependency jose to v6 (#1248)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [jose](https://redirect.github.com/panva/jose) | [`^5.9.6` ->
`^6.0.0`](https://renovatebot.com/diffs/npm/jose/5.10.0/6.0.10) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/jose/6.0.10?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/jose/6.0.10?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/jose/5.10.0/6.0.10?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/jose/5.10.0/6.0.10?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>panva/jose (jose)</summary>

###
[`v6.0.10`](https://redirect.github.com/panva/jose/blob/HEAD/CHANGELOG.md#6010-2025-03-12)

[Compare
Source](https://redirect.github.com/panva/jose/compare/v6.0.9...v6.0.10)

##### Refactor

- removed unused claims methods
([74719cf](74719cfcfb))
- reorganize jwt claim set utils
([1f12d88](1f12d88ee8))

###
[`v6.0.9`](https://redirect.github.com/panva/jose/blob/HEAD/CHANGELOG.md#609-2025-03-11)

[Compare
Source](https://redirect.github.com/panva/jose/compare/v6.0.8...v6.0.9)

##### Documentation

- add more symbol document, ignore ts-private fields
([8b73687](8b73687595))
- bump typedoc
([6163a8b](6163a8b6a7))
- drop cdnjs links in README
([a910038](a9100383ab))
- drop denoland/x links in README and add jsr
([3662b9e](3662b9ec44))
- fix key export links from docs/README.md
([c8edfc2](c8edfc2941))

##### Refactor

- always assume structuredClone is present
([f7898a9](f7898a9487))
- hide internal private fields and drop ProduceJWT inheritance
([ab18881](ab18881a57))
- less objects when JWE JWT Replicated Header Parameters are used
([c763a0e](c763a0e373))

###
[`v6.0.8`](https://redirect.github.com/panva/jose/blob/HEAD/CHANGELOG.md#608-2025-02-26)

[Compare
Source](https://redirect.github.com/panva/jose/compare/v6.0.7...v6.0.8)

##### Fixes

- export \[customFetch] symbol from the default entrypoint
([1615614](1615614964)),
closes [#&#8203;762](https://redirect.github.com/panva/jose/issues/762)

###
[`v6.0.7`](https://redirect.github.com/panva/jose/blob/HEAD/CHANGELOG.md#607-2025-02-25)

[Compare
Source](https://redirect.github.com/panva/jose/compare/v6.0.6...v6.0.7)

##### Documentation

- improve generate key/secret and import function descriptions
([cd06359](cd06359597))

##### Fixes

- use \[customFetch] when provided to createRemoteJWKSet
([35f6509](35f6509ff4)),
closes [#&#8203;760](https://redirect.github.com/panva/jose/issues/760)

###
[`v6.0.6`](https://redirect.github.com/panva/jose/blob/HEAD/CHANGELOG.md#606-2025-02-23)

[Compare
Source](https://redirect.github.com/panva/jose/compare/v6.0.5...v6.0.6)

##### Refactor

- move base64url around
([e1350ef](e1350eff87))

##### Documentation

- add various exported symbol descriptions
([3b8ff71](3b8ff717ad))
- add various exported symbol descriptions
([fc4e7da](fc4e7dab4c))
- add various exported symbol descriptions
([74f02c8](74f02c833e))
- update base64url function descriptions
([03d72c8](03d72c8a55))

###
[`v6.0.5`](https://redirect.github.com/panva/jose/blob/HEAD/CHANGELOG.md#605-2025-02-23)

[Compare
Source](https://redirect.github.com/panva/jose/compare/v6.0.4...v6.0.5)

##### Refactor

- **types:** make JWKParameters.kty compatible with
[@&#8203;types/node](https://redirect.github.com/types/node) and
[@&#8203;types/web](https://redirect.github.com/types/web)
([bb6ccfe](bb6ccfed3e))

##### Documentation

- add various exported symbol descriptions
([f52c2ff](f52c2ff0c3))

###
[`v6.0.4`](https://redirect.github.com/panva/jose/blob/HEAD/CHANGELOG.md#604-2025-02-22)

[Compare
Source](https://redirect.github.com/panva/jose/compare/v6.0.3...v6.0.4)

##### Refactor

- optimize base64 with tc39/proposal-arraybuffer-base64
([8a0da69](8a0da6968e)),
closes [#&#8203;752](https://redirect.github.com/panva/jose/issues/752)
- update getSPKI to use crypto.createPublicKey when available
([92392a0](92392a0aa2)),
closes [#&#8203;752](https://redirect.github.com/panva/jose/issues/752)
- use Double HMAC pattern for AES-CBC tag comparison
([f3ba4c7](f3ba4c715f)),
closes [#&#8203;752](https://redirect.github.com/panva/jose/issues/752)

###
[`v6.0.3`](https://redirect.github.com/panva/jose/blob/HEAD/CHANGELOG.md#603-2025-02-22)

[Compare
Source](https://redirect.github.com/panva/jose/compare/v6.0.2...v6.0.3)

##### Documentation

- remove root module tag so that README.md shows up on jsr.io
([ee70698](ee7069818b))

###
[`v6.0.2`](https://redirect.github.com/panva/jose/blob/HEAD/CHANGELOG.md#602-2025-02-22)

[Compare
Source](https://redirect.github.com/panva/jose/compare/v6.0.1...v6.0.2)

##### Documentation

- add module tags to all entrypoints
([a5687aa](a5687aaed4))

###
[`v6.0.1`](https://redirect.github.com/panva/jose/blob/HEAD/CHANGELOG.md#601-2025-02-22)

[Compare
Source](https://redirect.github.com/panva/jose/compare/v6.0.0...v6.0.1)

##### Fixes

- **types:** update build to include extensions in type imports
([9b96672](9b96672ef7))

###
[`v6.0.0`](https://redirect.github.com/panva/jose/blob/HEAD/CHANGELOG.md#600-2025-02-22)

[Compare
Source](https://redirect.github.com/panva/jose/compare/v5.10.0...v6.0.0)

##### ⚠ BREAKING CHANGES

-   The PEMImportOptions type interface is renamed to KeyImportOptions.
-   all builds and bundles now use ES2022 as target
- createRemoteJWKSet now uses fetch, because of that its Node.js only
options.agent property has been removed and new fetch-related options
were added
-   drop support for Ed448 and X448
- drop support for JWK key_ops and CryptoKey usages "(un)wrapKey" and
"deriveKey"
- resolved keys returned as part of verify/decrypt operations (when get
key functions are used) are always normalized to either Uint8Array /
CryptoKey depending on what's more efficient for the executed operation
-   Key "Type" Generics are removed
- CJS-style require is now only possible when require(esm) support is
present in the Node.js runtime
- private KeyObject instances can no longer be used for verify
operations
- private KeyObject instances can no longer be used for encryption
operations
- generateSecret, generateKeyPair, importPKCS8, importSPKI, importJWK,
and importX509 now yield a CryptoKey instead of a KeyObject in Node.js
-   drop support for Node.js 18.x and earlier
- runtime-specific npm releases (jose-browser-runtime,
jose-node-cjs-runtime, and jose-node-esm-runtime) are no longer
maintained or supported
-   removed secp256k1 JWS support
-   removed deprecated experimental APIs
-   removed RSA1\_5 JWE support

##### Features

- enable CryptoKey and KeyObject inputs in JWK thumbprint functions
([6fc9c44](6fc9c4461a))
- JSON Web Key is now an allowed input everywhere
([ebda967](ebda9674e9))

##### Refactor

- always use infered CryptoKey
([c4abaa2](c4abaa265e))
- backport the
[`Ed25519`](https://redirect.github.com/panva/jose/commit/Ed25519) JWS
Algorithm Identifier support
([7a94cb9](7a94cb997a))
- drop support for Ed448 and X448
([2fae1c4](2fae1c447b))
- drop support for JWK key_ops and CryptoKey usages "(un)wrapKey" and
"deriveKey"
([ef918be](ef918be8ba))
- ensure export functions continue to work with KeyObject inputs
([28e9e68](28e9e684bb))
- hardcode the cryptoRuntime export since it is now always WebCryptoAPI
([e00f273](e00f2737fd))
- JWK import extractable default for public keys is now true
([64dcebe](64dcebef36))
- PEM import extractable default for public keys is now true
([4e9f114](4e9f1143c7))
- removed deprecated APIs
([5352083](5352083dc6))
- removed secp256k1 JWS support
([e2b58a5](e2b58a5ca5))
- restructure src/lib and src/runtime now that runtime is fixed
([9b236ce](9b236cec4e))
- target is now ES2022 everywhere
([aa590d5](aa590d569f))
- update importJWK args to align with other import functions
([355a2dd](355a2dd33a))
- WebCryptoAPI is now the only crypto used
([161de46](161de466a2))

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update
again.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-19 22:18:27 -04:00
Eli Bosley
7bc9949110 fix: make scripts executable when building the plugin (#1255)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Enhanced script functionality to automatically set correct executable
permissions for files within "scripts" directories, ensuring that all
relevant scripts run as expected.
- Added symbolic link management for various Node.js binaries, improving
accessibility and organization within the application.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-03-19 21:13:30 -04:00
renovate[bot]
ad3906e682 fix(deps): update all non-major dependencies (#1251)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [graphql-scalars](https://redirect.github.com/Urigo/graphql-scalars) |
[`1.24.1` ->
`1.24.2`](https://renovatebot.com/diffs/npm/graphql-scalars/1.24.1/1.24.2)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/graphql-scalars/1.24.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/graphql-scalars/1.24.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/graphql-scalars/1.24.1/1.24.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/graphql-scalars/1.24.1/1.24.2?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [nestjs-pino](https://redirect.github.com/iamolegga/nestjs-pino) |
[`4.3.1` ->
`4.4.0`](https://renovatebot.com/diffs/npm/nestjs-pino/4.3.1/4.4.0) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/nestjs-pino/4.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/nestjs-pino/4.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/nestjs-pino/4.3.1/4.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/nestjs-pino/4.3.1/4.4.0?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [pnpm](https://pnpm.io)
([source](https://redirect.github.com/pnpm/pnpm/tree/HEAD/pnpm)) |
[`10.6.4` ->
`10.6.5`](https://renovatebot.com/diffs/npm/pnpm/10.6.4/10.6.5) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/pnpm/10.6.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/pnpm/10.6.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/pnpm/10.6.4/10.6.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/pnpm/10.6.4/10.6.5?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [vitest](https://redirect.github.com/vitest-dev/vitest)
([source](https://redirect.github.com/vitest-dev/vitest/tree/HEAD/packages/vitest))
| [`3.0.7` ->
`3.0.9`](https://renovatebot.com/diffs/npm/vitest/3.0.7/3.0.9) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/vitest/3.0.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vitest/3.0.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vitest/3.0.7/3.0.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vitest/3.0.7/3.0.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [zx](https://google.github.io/zx/)
([source](https://redirect.github.com/google/zx)) | [`8.3.2` ->
`8.4.1`](https://renovatebot.com/diffs/npm/zx/8.3.2/8.4.1) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/zx/8.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/zx/8.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/zx/8.3.2/8.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/zx/8.3.2/8.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>Urigo/graphql-scalars (graphql-scalars)</summary>

###
[`v1.24.2`](https://redirect.github.com/Urigo/graphql-scalars/blob/HEAD/CHANGELOG.md#1242)

[Compare
Source](https://redirect.github.com/Urigo/graphql-scalars/compare/v1.24.1...v1.24.2)

##### Patch Changes

-
[#&#8203;2791](https://redirect.github.com/graphql-hive/graphql-scalars/pull/2791)

[`3e1e924`](3e1e924b93)
Thanks [@&#8203;dotansimha](https://redirect.github.com/dotansimha)! -
Enable npm provenance

</details>

<details>
<summary>iamolegga/nestjs-pino (nestjs-pino)</summary>

###
[`v4.4.0`](https://redirect.github.com/iamolegga/nestjs-pino/releases/tag/4.4.0):
: allow publishing source map files

[Compare
Source](https://redirect.github.com/iamolegga/nestjs-pino/compare/4.3.1...4.4.0)

#### What's Changed

- build(deps-dev): bump prettier from 3.5.1 to 3.5.2 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2255](https://redirect.github.com/iamolegga/nestjs-pino/pull/2255)
- build(deps-dev): bump
[@&#8203;eslint/js](https://redirect.github.com/eslint/js) from 9.20.0
to 9.21.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2256](https://redirect.github.com/iamolegga/nestjs-pino/pull/2256)
- build(deps-dev): bump
[@&#8203;types/node](https://redirect.github.com/types/node) from
22.13.4 to 22.13.5 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2257](https://redirect.github.com/iamolegga/nestjs-pino/pull/2257)
- build(deps-dev): bump ts-jest from 29.2.5 to 29.2.6 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2258](https://redirect.github.com/iamolegga/nestjs-pino/pull/2258)
- build(deps-dev): bump
[@&#8203;eslint/eslintrc](https://redirect.github.com/eslint/eslintrc)
from 3.2.0 to 3.3.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2261](https://redirect.github.com/iamolegga/nestjs-pino/pull/2261)
- build(deps-dev): bump
[@&#8203;eslint/compat](https://redirect.github.com/eslint/compat) from
1.2.6 to 1.2.7 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2262](https://redirect.github.com/iamolegga/nestjs-pino/pull/2262)
- build(deps-dev): bump rxjs from 7.8.1 to 7.8.2 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2259](https://redirect.github.com/iamolegga/nestjs-pino/pull/2259)
- build(deps-dev): bump eslint from 9.20.1 to 9.21.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2260](https://redirect.github.com/iamolegga/nestjs-pino/pull/2260)
- build(deps-dev): bump
[@&#8203;typescript-eslint/eslint-plugin](https://redirect.github.com/typescript-eslint/eslint-plugin)
from 8.24.1 to 8.25.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2263](https://redirect.github.com/iamolegga/nestjs-pino/pull/2263)
- build(deps-dev): bump
[@&#8203;typescript-eslint/parser](https://redirect.github.com/typescript-eslint/parser)
from 8.24.1 to 8.25.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2264](https://redirect.github.com/iamolegga/nestjs-pino/pull/2264)
- build(deps-dev): bump eslint-config-prettier from 10.0.1 to 10.0.2 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2265](https://redirect.github.com/iamolegga/nestjs-pino/pull/2265)
- build(deps-dev): bump
[@&#8203;nestjs/testing](https://redirect.github.com/nestjs/testing)
from 11.0.10 to 11.0.11 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2267](https://redirect.github.com/iamolegga/nestjs-pino/pull/2267)
- build(deps-dev): bump
[@&#8203;types/node](https://redirect.github.com/types/node) from
22.13.5 to 22.13.8 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2268](https://redirect.github.com/iamolegga/nestjs-pino/pull/2268)
- build(deps-dev): bump
[@&#8203;nestjs/platform-express](https://redirect.github.com/nestjs/platform-express)
from 11.0.10 to 11.0.11 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2269](https://redirect.github.com/iamolegga/nestjs-pino/pull/2269)
- build(deps-dev): bump prettier from 3.5.2 to 3.5.3 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2271](https://redirect.github.com/iamolegga/nestjs-pino/pull/2271)
- build(deps-dev): bump
[@&#8203;nestjs/core](https://redirect.github.com/nestjs/core) from
11.0.10 to 11.0.11 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2272](https://redirect.github.com/iamolegga/nestjs-pino/pull/2272)
- build(deps-dev): bump
[@&#8203;nestjs/platform-fastify](https://redirect.github.com/nestjs/platform-fastify)
from 11.0.10 to 11.0.11 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2273](https://redirect.github.com/iamolegga/nestjs-pino/pull/2273)
- build(deps-dev): bump
[@&#8203;nestjs/common](https://redirect.github.com/nestjs/common) from
11.0.10 to 11.0.11 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2274](https://redirect.github.com/iamolegga/nestjs-pino/pull/2274)
- build(deps-dev): bump
[@&#8203;types/node](https://redirect.github.com/types/node) from
22.13.8 to 22.13.9 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2275](https://redirect.github.com/iamolegga/nestjs-pino/pull/2275)
- build(deps-dev): bump
[@&#8203;typescript-eslint/eslint-plugin](https://redirect.github.com/typescript-eslint/eslint-plugin)
from 8.25.0 to 8.26.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2276](https://redirect.github.com/iamolegga/nestjs-pino/pull/2276)
- build(deps-dev): bump
[@&#8203;typescript-eslint/parser](https://redirect.github.com/typescript-eslint/parser)
from 8.25.0 to 8.26.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2277](https://redirect.github.com/iamolegga/nestjs-pino/pull/2277)
- build(deps-dev): bump eslint from 9.21.0 to 9.22.0 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2278](https://redirect.github.com/iamolegga/nestjs-pino/pull/2278)
- build(deps-dev): bump
[@&#8203;types/node](https://redirect.github.com/types/node) from
22.13.9 to 22.13.10 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2280](https://redirect.github.com/iamolegga/nestjs-pino/pull/2280)
- build(deps-dev): bump eslint-config-prettier from 10.0.2 to 10.1.1 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2281](https://redirect.github.com/iamolegga/nestjs-pino/pull/2281)
- build(deps-dev): bump
[@&#8203;typescript-eslint/parser](https://redirect.github.com/typescript-eslint/parser)
from 8.26.0 to 8.26.1 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2284](https://redirect.github.com/iamolegga/nestjs-pino/pull/2284)
- build(deps-dev): bump
[@&#8203;typescript-eslint/eslint-plugin](https://redirect.github.com/typescript-eslint/eslint-plugin)
from 8.26.0 to 8.26.1 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2285](https://redirect.github.com/iamolegga/nestjs-pino/pull/2285)
- build(deps-dev): bump typescript from 5.7.3 to 5.8.2 by
[@&#8203;dependabot](https://redirect.github.com/dependabot) in
[https://github.com/iamolegga/nestjs-pino/pull/2270](https://redirect.github.com/iamolegga/nestjs-pino/pull/2270)
- chore(package): allow publishing source map files by
[@&#8203;H4ad](https://redirect.github.com/H4ad) in
[https://github.com/iamolegga/nestjs-pino/pull/2288](https://redirect.github.com/iamolegga/nestjs-pino/pull/2288)

#### New Contributors

- [@&#8203;H4ad](https://redirect.github.com/H4ad) made their first
contribution in
[https://github.com/iamolegga/nestjs-pino/pull/2288](https://redirect.github.com/iamolegga/nestjs-pino/pull/2288)

**Full Changelog**:
https://github.com/iamolegga/nestjs-pino/compare/4.3.1...4.4.0

</details>

<details>
<summary>pnpm/pnpm (pnpm)</summary>

###
[`v10.6.5`](https://redirect.github.com/pnpm/pnpm/compare/v10.6.4...v10.6.5)

[Compare
Source](https://redirect.github.com/pnpm/pnpm/compare/v10.6.4...v10.6.5)

</details>

<details>
<summary>vitest-dev/vitest (vitest)</summary>

###
[`v3.0.9`](https://redirect.github.com/vitest-dev/vitest/releases/tag/v3.0.9)

[Compare
Source](https://redirect.github.com/vitest-dev/vitest/compare/v3.0.8...v3.0.9)

#####    🐞 Bug Fixes

- Typings of `ctx.skip()` as `never`  -  by
[@&#8203;sirlancelot](https://redirect.github.com/sirlancelot) in
[https://github.com/vitest-dev/vitest/issues/7608](https://redirect.github.com/vitest-dev/vitest/issues/7608)
[<samp>(09f35)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/09f35301)
- Cleanup vitest in public `resolveConfig` API  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7623](https://redirect.github.com/vitest-dev/vitest/issues/7623)
[<samp>(db14a)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/db14ab71)
- Fix `toHaveBeenCalledWith(asymmetricMatcher)` with `undefined`
arguments  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7624](https://redirect.github.com/vitest-dev/vitest/issues/7624)
[<samp>(0fb21)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/0fb21faa)
- Race condition in RPC filesystem cache.  -  by
[@&#8203;dts](https://redirect.github.com/dts) in
[https://github.com/vitest-dev/vitest/issues/7531](https://redirect.github.com/vitest-dev/vitest/issues/7531)
[<samp>(b7f55)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/b7f55261)
- Fix `getState().testPath` during collection with no isolation  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7640](https://redirect.github.com/vitest-dev/vitest/issues/7640)
[<samp>(3fb3f)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/3fb3fbf8)
- Support custom toString method in %s format  -  by
[@&#8203;pengooseDev](https://redirect.github.com/pengooseDev) in
[https://github.com/vitest-dev/vitest/issues/7637](https://redirect.github.com/vitest-dev/vitest/issues/7637)
[<samp>(46d93)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/46d93a2e)
-   **browser**:
- Fail playwright timeouts earlier than a test timeout  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) and
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7565](https://redirect.github.com/vitest-dev/vitest/issues/7565)
[<samp>(5eb4c)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/5eb4cd1f)
- Remove
[@&#8203;testing-library/dom](https://redirect.github.com/testing-library/dom)
from dependencies
[#&#8203;7555](https://redirect.github.com/vitest-dev/vitest/issues/7555))"
 -  by [@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[https://github.com/vitest-dev/vitest/issues/7628](https://redirect.github.com/vitest-dev/vitest/issues/7628)
and
[https://github.com/vitest-dev/vitest/issues/7555](https://redirect.github.com/vitest-dev/vitest/issues/7555)
[<samp>(94b27)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/94b27af5)
-   **coverage**:
- Browser mode + `coverage.all`  -  by
[@&#8203;AriPerkkio](https://redirect.github.com/AriPerkkio) in
[https://github.com/vitest-dev/vitest/issues/7597](https://redirect.github.com/vitest-dev/vitest/issues/7597)
[<samp>(422ba)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/422ba66b)
-   **runner**:
- Show stacktrace on hook timeout error  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7502](https://redirect.github.com/vitest-dev/vitest/issues/7502)
[<samp>(268a1)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/268a19e1)
-   **vite-node**:
- Fix source map of inlined node_modules  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7557](https://redirect.github.com/vitest-dev/vitest/issues/7557)
[<samp>(34aa3)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/34aa322b)
- Fix missing `buildStart`  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7652](https://redirect.github.com/vitest-dev/vitest/issues/7652)
[<samp>(29f5a)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/29f5a848)
-   **web-worker**:
- Ensure `removeEventListener` is bound to worker  -  by
[@&#8203;joelgallant](https://redirect.github.com/joelgallant) in
[https://github.com/vitest-dev/vitest/issues/7631](https://redirect.github.com/vitest-dev/vitest/issues/7631)
[<samp>(ff42b)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/ff42bcb3)

#####     [View changes on
GitHub](https://redirect.github.com/vitest-dev/vitest/compare/v3.0.8...v3.0.9)

###
[`v3.0.8`](https://redirect.github.com/vitest-dev/vitest/releases/tag/v3.0.8)

[Compare
Source](https://redirect.github.com/vitest-dev/vitest/compare/v3.0.7...v3.0.8)

#####    🐞 Bug Fixes

- Fix fetch cache multiple writes  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7546](https://redirect.github.com/vitest-dev/vitest/issues/7546)
[<samp>(1a8b4)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/1a8b4337)
- Use browser.isolate instead of config.isolate  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[https://github.com/vitest-dev/vitest/issues/7560](https://redirect.github.com/vitest-dev/vitest/issues/7560)
[<samp>(4b5ed)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/4b5ed902)
- Remove vestigial spy stub, import directly from `@vitest/spy`  -  by
[@&#8203;mrginglymus](https://redirect.github.com/mrginglymus) in
[https://github.com/vitest-dev/vitest/issues/7575](https://redirect.github.com/vitest-dev/vitest/issues/7575)
[<samp>(7f7ff)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/7f7ff11c)
- Correctly split the argv string  -  by
[@&#8203;btea](https://redirect.github.com/btea) in
[https://github.com/vitest-dev/vitest/issues/7533](https://redirect.github.com/vitest-dev/vitest/issues/7533)
[<samp>(4325a)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/4325ac67)
-   **browser**:
- Remove
[@&#8203;testing-library/dom](https://redirect.github.com/testing-library/dom)
from dependencies  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[https://github.com/vitest-dev/vitest/issues/7555](https://redirect.github.com/vitest-dev/vitest/issues/7555)
[<samp>(5387a)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/5387a5b3)
- Improve source map handling for bundled files  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[https://github.com/vitest-dev/vitest/issues/7534](https://redirect.github.com/vitest-dev/vitest/issues/7534)
[<samp>(e2c57)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/e2c570b6)
- Print related test file and potential test in unhandled errors  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[https://github.com/vitest-dev/vitest/issues/7564](https://redirect.github.com/vitest-dev/vitest/issues/7564)
[<samp>(fee90)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/fee90d85)
-   **runner**:
- Fix `beforeEach/All` cleanup callback timeout  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7500](https://redirect.github.com/vitest-dev/vitest/issues/7500)
[<samp>(0c292)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/0c2924b7)
- Fix and simplify `Task.suite` initialization  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7414](https://redirect.github.com/vitest-dev/vitest/issues/7414)
[<samp>(ca9ff)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/ca9ffac5)
-   **snapshot**:
- Allow inline snapshot calls on same location with same snapshot  -  by
[@&#8203;jycouet](https://redirect.github.com/jycouet) and
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7464](https://redirect.github.com/vitest-dev/vitest/issues/7464)
[<samp>(d5cb8)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/d5cb8212)
-   **vite-node**:
- Fix `buildStart` on Vite 6  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7480](https://redirect.github.com/vitest-dev/vitest/issues/7480)
[<samp>(c0f47)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/c0f47e03)

#####     [View changes on
GitHub](https://redirect.github.com/vitest-dev/vitest/compare/v3.0.7...v3.0.8)

</details>

<details>
<summary>google/zx (zx)</summary>

###
[`v8.4.1`](https://redirect.github.com/google/zx/releases/tag/8.4.1): –
Rusty Elbow

[Compare
Source](https://redirect.github.com/google/zx/compare/8.4.0...8.4.1)

Logger enhancements are arriving in this release.
[#&#8203;1119](https://redirect.github.com/google/zx/issues/1119)
[#&#8203;1122](https://redirect.github.com/google/zx/pull/1122)
[#&#8203;1123](https://redirect.github.com/google/zx/pull/1123)
[#&#8203;1125](https://redirect.github.com/google/zx/pull/1125)

- You can customize the output by defining your own formatters for each
log entry kind.

```ts
$.log.formatters = {
  cmd: (entry: LogEntry) => `CMD: ${entry.cmd}`,
  fetch: (entry: LogEntry) => `FETCH: ${entry.url}`
  //...
}
```

- Cmd highlighter now *should* properly detect bins and arguments. If
still not, please report it in
[#&#8203;1122](https://redirect.github.com/google/zx/pull/1122)
- Switched to TS 5.8
[#&#8203;1120](https://redirect.github.com/google/zx/pull/1120)
- Applied [zizmor](https://woodruffw.github.io/zizmor/) to check GHA
workflows
[#&#8203;1126](https://redirect.github.com/google/zx/pull/1126)
- Prettier is now enabled as a pre-commit hook
[#&#8203;1118](https://redirect.github.com/google/zx/pull/1118)

###
[`v8.4.0`](https://redirect.github.com/google/zx/releases/tag/8.4.0): –
Drip Detective

[Compare
Source](https://redirect.github.com/google/zx/compare/8.3.2...8.4.0)

Try the new batch of enhancements: `npm i zx@8.4.0`
https://www.npmjs.com/package/zx/v/8.4.0

#### Changes

- The CLI option `--prefer-local` now allows linking both external
binaries and packages
[#&#8203;1116](https://redirect.github.com/google/zx/pull/1116)
[#&#8203;1117](https://redirect.github.com/google/zx/pull/1117)

```js
const cwd = tmpdir()
const external = tmpdir()
await fs.outputJson(path.join(external, 'node_modules/a/package.json'), {
  name: 'a',
  version: '1.0.0',
  type: 'module',
  exports: './index.js',
})
await fs.outputFile(
  path.join(external, 'node_modules/a/index.js'),
  `
export const a = 'AAA'
`
)
const script = `
import {a} from 'a'
console.log(a);
`
const out = await $`zx --cwd=${cwd} --prefer-local=${external} --test <<< ${script}`
assert.equal(out.stdout, 'AAA\n')
```

- The `quote` has been slightly changed for a conner case, when zx
literal gets an array.
[#&#8203;999](https://redirect.github.com/google/zx/issues/999)
[#&#8203;1113](https://redirect.github.com/google/zx/issues/1113)

```js
const p = $({prefix: '', postfix: ''})`echo ${[1, '', '*', '2']}`

// before
p.cmd //  `echo 1  $'*' 2`) 

// after
p.cmd //  `echo 1 $'' $'*' 2`) 
```

- Provided support for custom script extensions via CLI
[#&#8203;1104](https://redirect.github.com/google/zx/pull/1104)
[#&#8203;1105](https://redirect.github.com/google/zx/pull/1105)

```bash
zx script.zx           # Unknown file extension "\.zx"
zx --ext=mjs script.zx # OK
```

- Enhanced `nothrow` option to suppress any errors
[#&#8203;1108](https://redirect.github.com/google/zx/pull/1108)
[#&#8203;1109](https://redirect.github.com/google/zx/pull/1109)

```js
const err = new Error('BrokenSpawn')
const o = await $({
  nothrow: true,
  spawn() {
    throw err
  },
})`echo foo`
o.ok       // false
o.exitCode // null
o.message  // BrokenSpawn...
o.cause    // err
```

- `@types/node` and `@types/fs-extra` deps replaced with triple-slash
typing refs
[#&#8203;1102](https://redirect.github.com/google/zx/pull/1102)
- Made `ProcessOutput` iterable
[#&#8203;1101](https://redirect.github.com/google/zx/pull/1101)
- Handle inappropriate `ProcessPromise` instantiation
[#&#8203;1097](https://redirect.github.com/google/zx/pull/1097)
[#&#8203;1098](https://redirect.github.com/google/zx/pull/1098)
- Pass origin error as `ProcessOuput` cause
[#&#8203;1110](https://redirect.github.com/google/zx/pull/1110)
- Separated build and release steps
[#&#8203;1106](https://redirect.github.com/google/zx/pull/1106)
-   Internal improvements
- Introduced API bus
[#&#8203;1083](https://redirect.github.com/google/zx/pull/1083)
- Optimized `ProcessOutput` inners
[#&#8203;1096](https://redirect.github.com/google/zx/pull/1096)
[#&#8203;1095](https://redirect.github.com/google/zx/pull/1095)
- Pinned deps
[#&#8203;1099](https://redirect.github.com/google/zx/pull/1099)
[#&#8203;1100](https://redirect.github.com/google/zx/pull/1100)
- Switched to explicit `.ts` extensions for relative imports
[#&#8203;1111](https://redirect.github.com/google/zx/pull/1111)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-19 10:34:25 -04:00
Eli Bosley
a356bf03fb feat: make log viewer component dynamic (#1242)
<!-- This is an auto-generated comment: release notes by coderabbit.ai
-->
## Summary by CodeRabbit

- **New Features**
- Introduced a new Log Viewer configuration component to enhance the
management and application of log settings.

- **Chores**
- Removed the legacy log viewer interface to streamline log management
and improve the overall user experience.
<!-- end of auto-generated comment: release notes by coderabbit.ai -->
2025-03-19 10:33:12 -04:00
renovate[bot]
57a6c49f8a fix(deps): update all non-major dependencies (#1247)
This PR contains the following updates:

| Package | Change | Age | Adoption | Passing | Confidence |
|---|---|---|---|---|---|
| [@nestjs/common](https://nestjs.com)
([source](https://redirect.github.com/nestjs/nest/tree/HEAD/packages/common))
| [`11.0.11` ->
`11.0.12`](https://renovatebot.com/diffs/npm/@nestjs%2fcommon/11.0.11/11.0.12)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2fcommon/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2fcommon/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2fcommon/11.0.11/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2fcommon/11.0.11/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [@nestjs/core](https://nestjs.com)
([source](https://redirect.github.com/nestjs/nest/tree/HEAD/packages/core))
| [`11.0.11` ->
`11.0.12`](https://renovatebot.com/diffs/npm/@nestjs%2fcore/11.0.11/11.0.12)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2fcore/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2fcore/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2fcore/11.0.11/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2fcore/11.0.11/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [@nestjs/platform-fastify](https://nestjs.com)
([source](https://redirect.github.com/nestjs/nest/tree/HEAD/packages/platform-fastify))
| [`11.0.11` ->
`11.0.12`](https://renovatebot.com/diffs/npm/@nestjs%2fplatform-fastify/11.0.11/11.0.12)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2fplatform-fastify/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2fplatform-fastify/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2fplatform-fastify/11.0.11/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2fplatform-fastify/11.0.11/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [@nestjs/testing](https://nestjs.com)
([source](https://redirect.github.com/nestjs/nest/tree/HEAD/packages/testing))
| [`11.0.11` ->
`11.0.12`](https://renovatebot.com/diffs/npm/@nestjs%2ftesting/11.0.11/11.0.12)
|
[![age](https://developer.mend.io/api/mc/badges/age/npm/@nestjs%2ftesting/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/@nestjs%2ftesting/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/@nestjs%2ftesting/11.0.11/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/@nestjs%2ftesting/11.0.11/11.0.12?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [vitest](https://redirect.github.com/vitest-dev/vitest)
([source](https://redirect.github.com/vitest-dev/vitest/tree/HEAD/packages/vitest))
| [`3.0.7` ->
`3.0.9`](https://renovatebot.com/diffs/npm/vitest/3.0.7/3.0.9) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/vitest/3.0.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/vitest/3.0.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/vitest/3.0.7/3.0.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/vitest/3.0.7/3.0.9?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
| [zx](https://google.github.io/zx/)
([source](https://redirect.github.com/google/zx)) | [`8.3.2` ->
`8.4.1`](https://renovatebot.com/diffs/npm/zx/8.3.2/8.4.1) |
[![age](https://developer.mend.io/api/mc/badges/age/npm/zx/8.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![adoption](https://developer.mend.io/api/mc/badges/adoption/npm/zx/8.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![passing](https://developer.mend.io/api/mc/badges/compatibility/npm/zx/8.3.2/8.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|
[![confidence](https://developer.mend.io/api/mc/badges/confidence/npm/zx/8.3.2/8.4.1?slim=true)](https://docs.renovatebot.com/merge-confidence/)
|

---

### Release Notes

<details>
<summary>nestjs/nest (@&#8203;nestjs/common)</summary>

###
[`v11.0.12`](https://redirect.github.com/nestjs/nest/compare/v11.0.11...c58f49a3cc7b48916a98dcb81764ce77950d535a)

[Compare
Source](https://redirect.github.com/nestjs/nest/compare/v11.0.11...c58f49a3cc7b48916a98dcb81764ce77950d535a)

</details>

<details>
<summary>nestjs/nest (@&#8203;nestjs/core)</summary>

###
[`v11.0.12`](https://redirect.github.com/nestjs/nest/compare/v11.0.11...c58f49a3cc7b48916a98dcb81764ce77950d535a)

[Compare
Source](https://redirect.github.com/nestjs/nest/compare/v11.0.11...c58f49a3cc7b48916a98dcb81764ce77950d535a)

</details>

<details>
<summary>nestjs/nest (@&#8203;nestjs/platform-fastify)</summary>

###
[`v11.0.12`](https://redirect.github.com/nestjs/nest/compare/v11.0.11...c58f49a3cc7b48916a98dcb81764ce77950d535a)

[Compare
Source](https://redirect.github.com/nestjs/nest/compare/v11.0.11...c58f49a3cc7b48916a98dcb81764ce77950d535a)

</details>

<details>
<summary>nestjs/nest (@&#8203;nestjs/testing)</summary>

###
[`v11.0.12`](https://redirect.github.com/nestjs/nest/compare/v11.0.11...c58f49a3cc7b48916a98dcb81764ce77950d535a)

[Compare
Source](https://redirect.github.com/nestjs/nest/compare/v11.0.11...c58f49a3cc7b48916a98dcb81764ce77950d535a)

</details>

<details>
<summary>vitest-dev/vitest (vitest)</summary>

###
[`v3.0.9`](https://redirect.github.com/vitest-dev/vitest/releases/tag/v3.0.9)

[Compare
Source](https://redirect.github.com/vitest-dev/vitest/compare/v3.0.8...v3.0.9)

#####    🐞 Bug Fixes

- Typings of `ctx.skip()` as `never`  -  by
[@&#8203;sirlancelot](https://redirect.github.com/sirlancelot) in
[https://github.com/vitest-dev/vitest/issues/7608](https://redirect.github.com/vitest-dev/vitest/issues/7608)
[<samp>(09f35)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/09f35301)
- Cleanup vitest in public `resolveConfig` API  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7623](https://redirect.github.com/vitest-dev/vitest/issues/7623)
[<samp>(db14a)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/db14ab71)
- Fix `toHaveBeenCalledWith(asymmetricMatcher)` with `undefined`
arguments  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7624](https://redirect.github.com/vitest-dev/vitest/issues/7624)
[<samp>(0fb21)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/0fb21faa)
- Race condition in RPC filesystem cache.  -  by
[@&#8203;dts](https://redirect.github.com/dts) in
[https://github.com/vitest-dev/vitest/issues/7531](https://redirect.github.com/vitest-dev/vitest/issues/7531)
[<samp>(b7f55)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/b7f55261)
- Fix `getState().testPath` during collection with no isolation  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7640](https://redirect.github.com/vitest-dev/vitest/issues/7640)
[<samp>(3fb3f)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/3fb3fbf8)
- Support custom toString method in %s format  -  by
[@&#8203;pengooseDev](https://redirect.github.com/pengooseDev) in
[https://github.com/vitest-dev/vitest/issues/7637](https://redirect.github.com/vitest-dev/vitest/issues/7637)
[<samp>(46d93)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/46d93a2e)
-   **browser**:
- Fail playwright timeouts earlier than a test timeout  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) and
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7565](https://redirect.github.com/vitest-dev/vitest/issues/7565)
[<samp>(5eb4c)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/5eb4cd1f)
- Remove
[@&#8203;testing-library/dom](https://redirect.github.com/testing-library/dom)
from dependencies
[#&#8203;7555](https://redirect.github.com/vitest-dev/vitest/issues/7555))"
 -  by [@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[https://github.com/vitest-dev/vitest/issues/7628](https://redirect.github.com/vitest-dev/vitest/issues/7628)
and
[https://github.com/vitest-dev/vitest/issues/7555](https://redirect.github.com/vitest-dev/vitest/issues/7555)
[<samp>(94b27)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/94b27af5)
-   **coverage**:
- Browser mode + `coverage.all`  -  by
[@&#8203;AriPerkkio](https://redirect.github.com/AriPerkkio) in
[https://github.com/vitest-dev/vitest/issues/7597](https://redirect.github.com/vitest-dev/vitest/issues/7597)
[<samp>(422ba)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/422ba66b)
-   **runner**:
- Show stacktrace on hook timeout error  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7502](https://redirect.github.com/vitest-dev/vitest/issues/7502)
[<samp>(268a1)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/268a19e1)
-   **vite-node**:
- Fix source map of inlined node_modules  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7557](https://redirect.github.com/vitest-dev/vitest/issues/7557)
[<samp>(34aa3)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/34aa322b)
- Fix missing `buildStart`  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7652](https://redirect.github.com/vitest-dev/vitest/issues/7652)
[<samp>(29f5a)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/29f5a848)
-   **web-worker**:
- Ensure `removeEventListener` is bound to worker  -  by
[@&#8203;joelgallant](https://redirect.github.com/joelgallant) in
[https://github.com/vitest-dev/vitest/issues/7631](https://redirect.github.com/vitest-dev/vitest/issues/7631)
[<samp>(ff42b)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/ff42bcb3)

#####     [View changes on
GitHub](https://redirect.github.com/vitest-dev/vitest/compare/v3.0.8...v3.0.9)

###
[`v3.0.8`](https://redirect.github.com/vitest-dev/vitest/releases/tag/v3.0.8)

[Compare
Source](https://redirect.github.com/vitest-dev/vitest/compare/v3.0.7...v3.0.8)

#####    🐞 Bug Fixes

- Fix fetch cache multiple writes  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7546](https://redirect.github.com/vitest-dev/vitest/issues/7546)
[<samp>(1a8b4)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/1a8b4337)
- Use browser.isolate instead of config.isolate  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[https://github.com/vitest-dev/vitest/issues/7560](https://redirect.github.com/vitest-dev/vitest/issues/7560)
[<samp>(4b5ed)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/4b5ed902)
- Remove vestigial spy stub, import directly from `@vitest/spy`  -  by
[@&#8203;mrginglymus](https://redirect.github.com/mrginglymus) in
[https://github.com/vitest-dev/vitest/issues/7575](https://redirect.github.com/vitest-dev/vitest/issues/7575)
[<samp>(7f7ff)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/7f7ff11c)
- Correctly split the argv string  -  by
[@&#8203;btea](https://redirect.github.com/btea) in
[https://github.com/vitest-dev/vitest/issues/7533](https://redirect.github.com/vitest-dev/vitest/issues/7533)
[<samp>(4325a)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/4325ac67)
-   **browser**:
- Remove
[@&#8203;testing-library/dom](https://redirect.github.com/testing-library/dom)
from dependencies  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[https://github.com/vitest-dev/vitest/issues/7555](https://redirect.github.com/vitest-dev/vitest/issues/7555)
[<samp>(5387a)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/5387a5b3)
- Improve source map handling for bundled files  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[https://github.com/vitest-dev/vitest/issues/7534](https://redirect.github.com/vitest-dev/vitest/issues/7534)
[<samp>(e2c57)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/e2c570b6)
- Print related test file and potential test in unhandled errors  -  by
[@&#8203;sheremet-va](https://redirect.github.com/sheremet-va) in
[https://github.com/vitest-dev/vitest/issues/7564](https://redirect.github.com/vitest-dev/vitest/issues/7564)
[<samp>(fee90)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/fee90d85)
-   **runner**:
- Fix `beforeEach/All` cleanup callback timeout  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7500](https://redirect.github.com/vitest-dev/vitest/issues/7500)
[<samp>(0c292)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/0c2924b7)
- Fix and simplify `Task.suite` initialization  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7414](https://redirect.github.com/vitest-dev/vitest/issues/7414)
[<samp>(ca9ff)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/ca9ffac5)
-   **snapshot**:
- Allow inline snapshot calls on same location with same snapshot  -  by
[@&#8203;jycouet](https://redirect.github.com/jycouet) and
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7464](https://redirect.github.com/vitest-dev/vitest/issues/7464)
[<samp>(d5cb8)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/d5cb8212)
-   **vite-node**:
- Fix `buildStart` on Vite 6  -  by
[@&#8203;hi-ogawa](https://redirect.github.com/hi-ogawa) in
[https://github.com/vitest-dev/vitest/issues/7480](https://redirect.github.com/vitest-dev/vitest/issues/7480)
[<samp>(c0f47)</samp>](https://redirect.github.com/vitest-dev/vitest/commit/c0f47e03)

#####     [View changes on
GitHub](https://redirect.github.com/vitest-dev/vitest/compare/v3.0.7...v3.0.8)

</details>

<details>
<summary>google/zx (zx)</summary>

###
[`v8.4.1`](https://redirect.github.com/google/zx/releases/tag/8.4.1): –
Rusty Elbow

[Compare
Source](https://redirect.github.com/google/zx/compare/8.4.0...8.4.1)

Logger enhancements are arriving in this release.
[#&#8203;1119](https://redirect.github.com/google/zx/issues/1119)
[#&#8203;1122](https://redirect.github.com/google/zx/pull/1122)
[#&#8203;1123](https://redirect.github.com/google/zx/pull/1123)
[#&#8203;1125](https://redirect.github.com/google/zx/pull/1125)

- You can customize the output by defining your own formatters for each
log entry kind.

```ts
$.log.formatters = {
  cmd: (entry: LogEntry) => `CMD: ${entry.cmd}`,
  fetch: (entry: LogEntry) => `FETCH: ${entry.url}`
  //...
}
```

- Cmd highlighter now *should* properly detect bins and arguments. If
still not, please report it in
[#&#8203;1122](https://redirect.github.com/google/zx/pull/1122)
- Switched to TS 5.8
[#&#8203;1120](https://redirect.github.com/google/zx/pull/1120)
- Applied [zizmor](https://woodruffw.github.io/zizmor/) to check GHA
workflows
[#&#8203;1126](https://redirect.github.com/google/zx/pull/1126)
- Prettier is now enabled as a pre-commit hook
[#&#8203;1118](https://redirect.github.com/google/zx/pull/1118)

###
[`v8.4.0`](https://redirect.github.com/google/zx/releases/tag/8.4.0): –
Drip Detective

[Compare
Source](https://redirect.github.com/google/zx/compare/8.3.2...8.4.0)

Try the new batch of enhancements: `npm i zx@8.4.0`
https://www.npmjs.com/package/zx/v/8.4.0

#### Changes

- The CLI option `--prefer-local` now allows linking both external
binaries and packages
[#&#8203;1116](https://redirect.github.com/google/zx/pull/1116)
[#&#8203;1117](https://redirect.github.com/google/zx/pull/1117)

```js
const cwd = tmpdir()
const external = tmpdir()
await fs.outputJson(path.join(external, 'node_modules/a/package.json'), {
  name: 'a',
  version: '1.0.0',
  type: 'module',
  exports: './index.js',
})
await fs.outputFile(
  path.join(external, 'node_modules/a/index.js'),
  `
export const a = 'AAA'
`
)
const script = `
import {a} from 'a'
console.log(a);
`
const out = await $`zx --cwd=${cwd} --prefer-local=${external} --test <<< ${script}`
assert.equal(out.stdout, 'AAA\n')
```

- The `quote` has been slightly changed for a conner case, when zx
literal gets an array.
[#&#8203;999](https://redirect.github.com/google/zx/issues/999)
[#&#8203;1113](https://redirect.github.com/google/zx/issues/1113)

```js
const p = $({prefix: '', postfix: ''})`echo ${[1, '', '*', '2']}`

// before
p.cmd //  `echo 1  $'*' 2`) 

// after
p.cmd //  `echo 1 $'' $'*' 2`) 
```

- Provided support for custom script extensions via CLI
[#&#8203;1104](https://redirect.github.com/google/zx/pull/1104)
[#&#8203;1105](https://redirect.github.com/google/zx/pull/1105)

```bash
zx script.zx           # Unknown file extension "\.zx"
zx --ext=mjs script.zx # OK
```

- Enhanced `nothrow` option to suppress any errors
[#&#8203;1108](https://redirect.github.com/google/zx/pull/1108)
[#&#8203;1109](https://redirect.github.com/google/zx/pull/1109)

```js
const err = new Error('BrokenSpawn')
const o = await $({
  nothrow: true,
  spawn() {
    throw err
  },
})`echo foo`
o.ok       // false
o.exitCode // null
o.message  // BrokenSpawn...
o.cause    // err
```

- `@types/node` and `@types/fs-extra` deps replaced with triple-slash
typing refs
[#&#8203;1102](https://redirect.github.com/google/zx/pull/1102)
- Made `ProcessOutput` iterable
[#&#8203;1101](https://redirect.github.com/google/zx/pull/1101)
- Handle inappropriate `ProcessPromise` instantiation
[#&#8203;1097](https://redirect.github.com/google/zx/pull/1097)
[#&#8203;1098](https://redirect.github.com/google/zx/pull/1098)
- Pass origin error as `ProcessOuput` cause
[#&#8203;1110](https://redirect.github.com/google/zx/pull/1110)
- Separated build and release steps
[#&#8203;1106](https://redirect.github.com/google/zx/pull/1106)
-   Internal improvements
- Introduced API bus
[#&#8203;1083](https://redirect.github.com/google/zx/pull/1083)
- Optimized `ProcessOutput` inners
[#&#8203;1096](https://redirect.github.com/google/zx/pull/1096)
[#&#8203;1095](https://redirect.github.com/google/zx/pull/1095)
- Pinned deps
[#&#8203;1099](https://redirect.github.com/google/zx/pull/1099)
[#&#8203;1100](https://redirect.github.com/google/zx/pull/1100)
- Switched to explicit `.ts` extensions for relative imports
[#&#8203;1111](https://redirect.github.com/google/zx/pull/1111)

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined),
Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you
are satisfied.

♻ **Rebasing**: Whenever PR is behind base branch, or you tick the
rebase/retry checkbox.

👻 **Immortal**: This PR will be recreated if closed unmerged. Get
[config
help](https://redirect.github.com/renovatebot/renovate/discussions) if
that's undesired.

---

- [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check
this box

---

This PR was generated by [Mend Renovate](https://mend.io/renovate/).
View the [repository job
log](https://developer.mend.io/github/unraid/api).

<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzOS4yMDcuMSIsInVwZGF0ZWRJblZlciI6IjM5LjIwNy4xIiwidGFyZ2V0QnJhbmNoIjoibWFpbiIsImxhYmVscyI6W119-->

Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-03-19 10:01:29 -04:00
287 changed files with 7571 additions and 4358 deletions

View File

@@ -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'
---
<!--

View File

@@ -152,6 +152,11 @@ jobs:
with:
name: unraid-api
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)
@@ -316,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
@@ -347,6 +361,11 @@ jobs:
with:
name: unraid-api
path: ${{ github.workspace }}/plugin/api/
- name: Download PNPM Store
uses: actions/download-artifact@v4
with:
name: packed-pnpm-store
path: ${{ github.workspace }}/plugin/
- name: Extract Unraid API
run: |
mkdir -p ${{ github.workspace }}/plugin/source/dynamix.unraid.net/usr/local/unraid-api
@@ -355,6 +374,7 @@ jobs:
id: build-plugin
run: |
cd ${{ github.workspace }}/plugin
ls -al
pnpm run build:txz
if [ -n "${{ github.event.pull_request.number }}" ]; then
@@ -375,7 +395,6 @@ jobs:
echo "TAG=${TAG}" >> $GITHUB_OUTPUT
pnpm run build:plugin --tag="${TAG}" --base-url="${BASE_URL}"
- name: Ensure Plugin Files Exist
run: |
if [ ! -f ./deploy/*.plg ]; then
@@ -387,6 +406,7 @@ jobs:
echo "Error: .txz file not found in plugin/deploy/"
exit 1
fi
ls -al ./deploy
- name: Upload to GHA
uses: actions/upload-artifact@v4
with:
@@ -399,8 +419,13 @@ jobs:
AWS_SECRET_ACCESS_KEY: ${{ secrets.CF_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: auto
run: |
# Sync the deploy directory to the Cloudflare bucket - CRC32 is required for the checksum-algorithm on cloudflare (ref. https://community.cloudflare.com/t/an-error-occurred-internalerror-when-calling-the-putobject-operation/764905/8)
aws s3 sync deploy/ s3://${{ secrets.CF_BUCKET_PREVIEW }}/${{ steps.build-plugin.outputs.BUCKET_PATH }} --endpoint-url ${{ secrets.CF_ENDPOINT }} --checksum-algorithm CRC32
# 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'

View File

@@ -99,7 +99,12 @@ jobs:
AWS_DEFAULT_REGION: ${{ secrets.DO_SPACE_REGION }}
AWS_ENDPOINT_URL: https://${{ secrets.DO_SPACE_REGION }}.digitaloceanspaces.com
run: |
aws s3 sync . s3://${{ secrets.DO_SPACE_NAME }}/unraid-api --checksum-algorithm CRC32
# 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:
@@ -108,4 +113,9 @@ jobs:
AWS_DEFAULT_REGION: auto
AWS_ENDPOINT_URL: ${{ secrets.CF_ENDPOINT }}
run: |
aws s3 sync . s3://${{ secrets.CF_BUCKET }}/unraid-api --checksum-algorithm CRC32
# 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

7
.gitignore vendored
View File

@@ -88,7 +88,6 @@ deploy/*
.nitro
.cache
.output
.env*
!.env.example
fb_keepalive
@@ -101,3 +100,9 @@ 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

View File

@@ -1 +1 @@
{".":"4.3.1"}
{".":"4.5.0"}

View File

@@ -1,3 +1,13 @@
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

4
api/.env.staging Normal file
View 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"

5
api/.gqlconfig Normal file
View File

@@ -0,0 +1,5 @@
{
schema: {
files: 'src/graphql/schema/types/**/*.graphql'
}
}

11
api/.vscode/extensions.json vendored Normal file
View 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"
]
}

View File

@@ -1,5 +1,69 @@
# Changelog
## [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)

View 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
api/dev/data/machine-id Normal file
View File

@@ -0,0 +1 @@
d0b5433294c110f1eed72bdb63910a9a

View File

@@ -0,0 +1 @@
version="6.12.0-beta5"

BIN
api/dev/dynamix/banner.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 61 KiB

View File

@@ -0,0 +1 @@
case-model.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.5 KiB

0
api/dev/states/devs.ini Normal file
View File

View File

@@ -1,5 +1,5 @@
[api]
version="4.1.3"
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=""

View 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
View 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=""

View 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
View 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
View 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"

View File

@@ -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"

View File

@@ -1,6 +1,6 @@
{
"name": "@unraid/api",
"version": "4.3.1",
"version": "4.5.0",
"main": "src/cli/index.ts",
"type": "module",
"corepack": {
@@ -8,7 +8,7 @@
},
"repository": "git@github.com:unraid/api.git",
"author": "Lime Technology, Inc. <unraid.net>",
"license": "GPL-2.0-only",
"license": "GPL-2.0-or-later",
"engines": {
"pnpm": ">=8.0.0"
},
@@ -17,6 +17,7 @@
"start": "node dist/main.js",
"dev": "vite",
"command": "pnpm run build && clear && ./dist/cli.js",
"command:raw": "./dist/cli.js",
"// Build and Deploy": "",
"build": "vite build --mode=production",
"postbuild": "chmod +x dist/main.js && chmod +x dist/cli.js",
@@ -77,6 +78,7 @@
"cacheable-lookup": "^7.0.0",
"camelcase-keys": "^9.1.3",
"casbin": "^5.32.0",
"change-case": "^5.4.4",
"chokidar": "^4.0.1",
"cli-table": "^0.3.11",
"command-exists": "^1.2.9",
@@ -103,10 +105,10 @@
"graphql-tag": "^2.12.6",
"graphql-type-json": "^0.3.2",
"graphql-type-uuid": "^0.2.0",
"graphql-ws": "^5.16.0",
"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",
@@ -121,8 +123,8 @@
"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",
@@ -143,7 +145,7 @@
"@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.4",
"@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": "^11.0.11",
@@ -163,7 +165,7 @@
"@types/lodash": "^4.17.13",
"@types/mustache": "^4.2.5",
"@types/node": "^22.13.4",
"@types/pify": "^5.0.4",
"@types/pify": "^6.0.0",
"@types/semver": "^7.5.8",
"@types/sendmail": "^1.4.7",
"@types/stoppable": "^1.1.3",
@@ -186,6 +188,7 @@
"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",
@@ -201,5 +204,5 @@
}
},
"private": true,
"packageManager": "pnpm@10.6.4"
"packageManager": "pnpm@10.7.1"
}

View File

@@ -25,6 +25,8 @@ 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 });
@@ -36,9 +38,18 @@ try {
// 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`;

View File

@@ -0,0 +1,3 @@
import { test } from 'vitest';
test.todo('Returns generated data');

View File

@@ -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');

View File

@@ -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');

View File

@@ -0,0 +1,5 @@
import { test } from 'vitest';
test.todo('Starts the array');
test.todo('Stops the array');

View File

@@ -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');

View File

@@ -0,0 +1,3 @@
import { test } from 'vitest';
test.todo('Returns the current content');

View 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');

View File

@@ -0,0 +1,5 @@
import { test } from 'vitest';
test.todo('Returns all the Docker containers');
test.todo('Returns running Docker containers');

View File

@@ -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');

View File

@@ -0,0 +1,3 @@
import { test } from 'vitest';
test.todo('Gets total count of Docker containers installed/running');

View File

@@ -0,0 +1,3 @@
import { test } from 'vitest';
test.todo('Returns baseboard info');

View File

@@ -0,0 +1,3 @@
import { test } from 'vitest';
test.todo('Gets CPU info');

View File

@@ -1,23 +0,0 @@
import { expect, test, vi } from 'vitest';
import type { SliceState } from '@app/store/modules/emhttp.js';
import { getters } from '@app/store/index.js';
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.js');
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.js');
expect(arrayIsRunning()).toBe(false);
vi.spyOn(getters, 'emhttp').mockReset();
});

View File

@@ -0,0 +1,3 @@
import { test } from 'vitest';
test.todo('Sleeps atomically for n milliseconds');

View File

@@ -0,0 +1,3 @@
import { test } from 'vitest';
test.todo('Returns machine-id');

View File

@@ -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": "",
}
`);
});

View File

@@ -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": "",
}
`);
});

View File

@@ -20,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: {

View File

@@ -2,7 +2,6 @@ import { GraphQLError } from 'graphql';
import { sum } from 'lodash-es';
import type { ArrayCapacity, ArrayType } from '@app/graphql/generated/api/types.js';
import { getServerIdentifier } from '@app/core/utils/server-identifier.js';
import { ArrayDiskType } from '@app/graphql/generated/api/types.js';
import { store } from '@app/store/index.js';
import { FileLoadStatus } from '@app/store/types.js';

View File

@@ -1,7 +1,6 @@
import fs from 'fs';
import camelCaseKeys from 'camelcase-keys';
import { ContainerInfo } from 'dockerode';
import type { ContainerPort, Docker, DockerContainer } from '@app/graphql/generated/api/types.js';
import { dockerLogger } from '@app/core/log.js';
@@ -11,13 +10,16 @@ import { ContainerPortType, ContainerState } from '@app/graphql/generated/api/ty
import { getters, store } from '@app/store/index.js';
import { updateDockerState } from '@app/store/modules/docker.js';
export interface ContainerListingOptions {
useCache?: boolean;
}
/**
* Get all Docker containers.
* @returns All the in/active Docker containers on the system.
*/
export const getDockerContainers = async (
{ useCache } = { useCache: true }
{ useCache }: ContainerListingOptions = { useCache: true }
): Promise<Array<DockerContainer>> => {
const dockerState = getters.docker();
if (useCache && dockerState.containers) {

View File

@@ -0,0 +1,2 @@
export type Device = Record<string, unknown>;
export type Devices = Array<Record<string, unknown>>;

View File

@@ -1,9 +1,10 @@
import {
type ArrayState,
type DiskFsType,
type RegistrationState,
type registrationType,
import type {
ArrayState,
DiskFsType,
RegistrationState,
registrationType,
} from '@app/graphql/generated/api/types.js';
import { ConfigErrorState } from '@app/graphql/generated/api/types.js';
/**
* Global vars
@@ -17,7 +18,7 @@ export type Var = {
/** Is the array's config valid. */
configValid: boolean;
/** @internal used to hold the value for config.error */
configState: string;
configErrorState: ConfigErrorState | null;
/** Current CSRF token for HTTP requests with emhttpd. */
csrfToken: string;
defaultFormat: string;

View File

@@ -1,8 +1,8 @@
import { got } from 'got';
import { AppError } from '@app/core/errors/app-error.js';
import { logger } from '@app/core/log.js';
import { type LooseObject } from '@app/core/types/index.js';
import { catchHandlers } from '@app/core/utils/misc/catch-handlers.js';
import { DRY_RUN } from '@app/environment.js';
import { getters } from '@app/store/index.js';
@@ -27,10 +27,15 @@ export const emcmd = async (commands: LooseObject) => {
// Ensure we only log on dry-run
return;
}
// Untested, this code is unused right now so going to assume it's probably not working well anyway, swapped
// to got to remove this request-promise dependency
return got
.get(url, { searchParams: { ...commands, csrf_token: csrfToken } })
.catch(catchHandlers.emhttpd);
// return request.get(url, options).catch(catchHandlers.emhttpd);
.get(url, {
enableUnixSockets: true,
searchParams: { ...commands, csrf_token: csrfToken },
})
.catch((error: NodeJS.ErrnoException) => {
if (error.code === 'ENOENT') {
throw new AppError('emhttpd socket unavailable.');
}
throw error;
});
};

View File

@@ -0,0 +1,3 @@
import { extname } from 'path';
export const getExtensionFromPath = (filePath: string): string => extname(filePath);

View File

@@ -3,36 +3,57 @@ import { homedir } from 'node:os';
import { join } from 'node:path';
import { fileURLToPath } from 'node:url';
const getPackageJsonVersion = () => {
import type { PackageJson, SetRequired } from 'type-fest';
/**
* Tries to get the package.json at the given location.
* @param location - The location of the package.json file, relative to the current file
* @returns The package.json object or undefined if unable to read
*/
function readPackageJson(location: string): PackageJson | undefined {
try {
// Try different possible locations for package.json
const possibleLocations = ['../package.json', '../../package.json'];
for (const location of possibleLocations) {
try {
const packageJsonUrl = import.meta.resolve(location);
const packageJsonPath = fileURLToPath(packageJsonUrl);
const packageJson = readFileSync(packageJsonPath, 'utf-8');
const packageJsonObject = JSON.parse(packageJson);
if (packageJsonObject.version) {
return packageJsonObject.version;
}
} catch {
// Continue to next location if this one fails
}
let packageJsonPath: string;
try {
const packageJsonUrl = import.meta.resolve(location);
packageJsonPath = fileURLToPath(packageJsonUrl);
} catch {
// Fallback (e.g. for local development): resolve the path relative to this module
packageJsonPath = fileURLToPath(new URL(location, import.meta.url));
}
// If we get here, we couldn't find a valid package.json in any location
console.error('Could not find package.json in any of the expected locations');
return undefined;
} catch (error) {
console.error('Failed to load package.json:', error);
const packageJsonRaw = readFileSync(packageJsonPath, 'utf-8');
return JSON.parse(packageJsonRaw) as PackageJson;
} catch {
return undefined;
}
}
/**
* Retrieves the Unraid API package.json. Throws if unable to find.
* This should be considered a fatal error.
*
* @returns The package.json object
*/
export const getPackageJson = () => {
const packageJson = readPackageJson('../package.json') || readPackageJson('../../package.json');
if (!packageJson) {
throw new Error('Could not find package.json in any of the expected locations');
}
return packageJson as SetRequired<PackageJson, 'version' | 'dependencies'>;
};
export const API_VERSION =
process.env.npm_package_version ?? getPackageJsonVersion() ?? new Error('API_VERSION not set');
/**
* Returns list of runtime dependencies from the Unraid-API package.json. Returns undefined if
* the package.json or its dependency object cannot be found or read.
*
* Does not log or produce side effects.
* @returns The names of all runtime dependencies. Undefined if failed.
*/
export const getPackageJsonDependencies = (): string[] | undefined => {
const { dependencies } = getPackageJson();
return Object.keys(dependencies);
};
export const API_VERSION = process.env.npm_package_version ?? getPackageJson().version;
export const NODE_ENV =
(process.env.NODE_ENV as 'development' | 'test' | 'staging' | 'production') ?? 'production';

View File

@@ -2,7 +2,7 @@
import * as Types from '@app/graphql/generated/api/types.js';
import { z } from 'zod'
import { AccessUrl, AccessUrlInput, AddPermissionInput, AddRoleForApiKeyInput, AddRoleForUserInput, AllowedOriginInput, ApiKey, ApiKeyResponse, ApiKeyWithSecret, ApiSettingsInput, ArrayType, ArrayCapacity, ArrayDisk, ArrayDiskFsColor, ArrayDiskStatus, ArrayDiskType, ArrayPendingState, ArrayState, Baseboard, Capacity, Case, Cloud, CloudResponse, Config, ConfigErrorState, Connect, ConnectSettings, ConnectSettingsValues, ConnectSignInInput, ConnectUserInfoInput, ContainerHostConfig, ContainerMount, ContainerPort, ContainerPortType, ContainerState, CreateApiKeyInput, Devices, Disk, DiskFsType, DiskInterfaceType, DiskPartition, DiskSmartStatus, Display, Docker, DockerContainer, DockerNetwork, DynamicRemoteAccessStatus, DynamicRemoteAccessType, EnableDynamicRemoteAccessInput, Flash, Gpu, Importance, Info, InfoApps, InfoCpu, InfoMemory, KeyFile, LogFile, LogFileContent, Me, MemoryFormFactor, MemoryLayout, MemoryType, MinigraphStatus, MinigraphqlResponse, Mount, Network, Node, Notification, NotificationCounts, NotificationData, NotificationFilter, NotificationOverview, NotificationType, Notifications, NotificationslistArgs, Os, Owner, ParityCheck, Partition, Pci, Permission, ProfileModel, Registration, RegistrationState, RelayResponse, RemoteAccess, RemoveRoleFromApiKeyInput, Resource, Role, Server, ServerStatus, Service, SetupRemoteAccessInput, Share, System, Temperature, Theme, URL_TYPE, UnassignedDevice, Uptime, Usb, User, UserAccount, Vars, Versions, VmDomain, VmState, Vms, WAN_ACCESS_TYPE, WAN_FORWARD_TYPE, Welcome, addUserInput, arrayDiskInput, deleteUserInput, mdState, registrationType, usersInput } from '@app/graphql/generated/api/types.js'
import { AccessUrl, AccessUrlInput, AddPermissionInput, AddRoleForApiKeyInput, AddRoleForUserInput, AllowedOriginInput, ApiKey, ApiKeyResponse, ApiKeyWithSecret, ApiSettingsInput, ArrayType, ArrayCapacity, ArrayDisk, ArrayDiskFsColor, ArrayDiskInput, ArrayDiskStatus, ArrayDiskType, ArrayMutations, ArrayMutationsaddDiskToArrayArgs, ArrayMutationsclearArrayDiskStatisticsArgs, ArrayMutationsmountArrayDiskArgs, ArrayMutationsremoveDiskFromArrayArgs, ArrayMutationssetStateArgs, ArrayMutationsunmountArrayDiskArgs, ArrayPendingState, ArrayState, ArrayStateInput, ArrayStateInputState, Baseboard, Capacity, Case, Cloud, CloudResponse, Config, ConfigErrorState, Connect, ConnectSettings, ConnectSettingsValues, ConnectSignInInput, ConnectUserInfoInput, ContainerHostConfig, ContainerMount, ContainerPort, ContainerPortType, ContainerState, CreateApiKeyInput, Devices, Disk, DiskFsType, DiskInterfaceType, DiskPartition, DiskSmartStatus, Display, Docker, DockerContainer, DockerMutations, DockerMutationsstartContainerArgs, DockerMutationsstopContainerArgs, DockerNetwork, DynamicRemoteAccessStatus, DynamicRemoteAccessType, EnableDynamicRemoteAccessInput, Flash, Gpu, Importance, Info, InfoApps, InfoCpu, InfoMemory, KeyFile, LogFile, LogFileContent, Me, MemoryFormFactor, MemoryLayout, MemoryType, MinigraphStatus, MinigraphqlResponse, Mount, Network, Node, Notification, NotificationCounts, NotificationData, NotificationFilter, NotificationOverview, NotificationType, Notifications, NotificationslistArgs, Os, Owner, ParityCheck, Partition, Pci, Permission, ProfileModel, Registration, RegistrationState, RelayResponse, RemoteAccess, RemoveRoleFromApiKeyInput, Resource, Role, Server, ServerStatus, Service, SetupRemoteAccessInput, Share, System, Temperature, Theme, URL_TYPE, UnassignedDevice, Uptime, Usb, User, UserAccount, Vars, Versions, VmDomain, VmState, Vms, WAN_ACCESS_TYPE, WAN_FORWARD_TYPE, Welcome, addUserInput, deleteUserInput, mdState, registrationType, usersInput } from '@app/graphql/generated/api/types.js'
import { TypedDocumentNode as DocumentNode } from '@graphql-typed-document-node/core';
type Properties<T> = Required<{
@@ -25,6 +25,8 @@ export const ArrayPendingStateSchema = z.nativeEnum(ArrayPendingState);
export const ArrayStateSchema = z.nativeEnum(ArrayState);
export const ArrayStateInputStateSchema = z.nativeEnum(ArrayStateInputState);
export const ConfigErrorStateSchema = z.nativeEnum(ConfigErrorState);
export const ContainerPortTypeSchema = z.nativeEnum(ContainerPortType);
@@ -213,6 +215,67 @@ export function ArrayDiskSchema(): z.ZodObject<Properties<ArrayDisk>> {
})
}
export function ArrayDiskInputSchema(): z.ZodObject<Properties<ArrayDiskInput>> {
return z.object({
id: z.string(),
slot: z.number().nullish()
})
}
export function ArrayMutationsSchema(): z.ZodObject<Properties<ArrayMutations>> {
return z.object({
__typename: z.literal('ArrayMutations').optional(),
addDiskToArray: ArrayTypeSchema().nullish(),
clearArrayDiskStatistics: z.record(z.string(), z.any()).nullish(),
mountArrayDisk: DiskSchema().nullish(),
removeDiskFromArray: ArrayTypeSchema().nullish(),
setState: ArrayTypeSchema().nullish(),
unmountArrayDisk: DiskSchema().nullish()
})
}
export function ArrayMutationsaddDiskToArrayArgsSchema(): z.ZodObject<Properties<ArrayMutationsaddDiskToArrayArgs>> {
return z.object({
input: z.lazy(() => ArrayDiskInputSchema().nullish())
})
}
export function ArrayMutationsclearArrayDiskStatisticsArgsSchema(): z.ZodObject<Properties<ArrayMutationsclearArrayDiskStatisticsArgs>> {
return z.object({
id: z.string()
})
}
export function ArrayMutationsmountArrayDiskArgsSchema(): z.ZodObject<Properties<ArrayMutationsmountArrayDiskArgs>> {
return z.object({
id: z.string()
})
}
export function ArrayMutationsremoveDiskFromArrayArgsSchema(): z.ZodObject<Properties<ArrayMutationsremoveDiskFromArrayArgs>> {
return z.object({
input: z.lazy(() => ArrayDiskInputSchema().nullish())
})
}
export function ArrayMutationssetStateArgsSchema(): z.ZodObject<Properties<ArrayMutationssetStateArgs>> {
return z.object({
input: z.lazy(() => ArrayStateInputSchema().nullish())
})
}
export function ArrayMutationsunmountArrayDiskArgsSchema(): z.ZodObject<Properties<ArrayMutationsunmountArrayDiskArgs>> {
return z.object({
id: z.string()
})
}
export function ArrayStateInputSchema(): z.ZodObject<Properties<ArrayStateInput>> {
return z.object({
desiredState: z.lazy(() => ArrayStateInputStateSchema)
})
}
export function BaseboardSchema(): z.ZodObject<Properties<Baseboard>> {
return z.object({
__typename: z.literal('Baseboard').optional(),
@@ -438,6 +501,7 @@ export function DockerSchema(): z.ZodObject<Properties<Docker>> {
__typename: z.literal('Docker').optional(),
containers: z.array(DockerContainerSchema()).nullish(),
id: z.string(),
mutations: DockerMutationsSchema(),
networks: z.array(DockerNetworkSchema()).nullish()
})
}
@@ -463,6 +527,26 @@ export function DockerContainerSchema(): z.ZodObject<Properties<DockerContainer>
})
}
export function DockerMutationsSchema(): z.ZodObject<Properties<DockerMutations>> {
return z.object({
__typename: z.literal('DockerMutations').optional(),
startContainer: DockerContainerSchema(),
stopContainer: DockerContainerSchema()
})
}
export function DockerMutationsstartContainerArgsSchema(): z.ZodObject<Properties<DockerMutationsstartContainerArgs>> {
return z.object({
id: z.string()
})
}
export function DockerMutationsstopContainerArgsSchema(): z.ZodObject<Properties<DockerMutationsstopContainerArgs>> {
return z.object({
id: z.string()
})
}
export function DockerNetworkSchema(): z.ZodObject<Properties<DockerNetwork>> {
return z.object({
__typename: z.literal('DockerNetwork').optional(),
@@ -611,6 +695,7 @@ export function LogFileContentSchema(): z.ZodObject<Properties<LogFileContent>>
__typename: z.literal('LogFileContent').optional(),
content: z.string(),
path: z.string(),
startLine: z.number().nullish(),
totalLines: z.number()
})
}
@@ -1302,13 +1387,6 @@ export function addUserInputSchema(): z.ZodObject<Properties<addUserInput>> {
})
}
export function arrayDiskInputSchema(): z.ZodObject<Properties<arrayDiskInput>> {
return z.object({
id: z.string(),
slot: z.number().nullish()
})
}
export function deleteUserInputSchema(): z.ZodObject<Properties<deleteUserInput>> {
return z.object({
name: z.string()

View File

@@ -191,6 +191,13 @@ export enum ArrayDiskFsColor {
YELLOW_ON = 'yellow_on'
}
export type ArrayDiskInput = {
/** Disk ID */
id: Scalars['ID']['input'];
/** The slot for the disk */
slot?: InputMaybe<Scalars['Int']['input']>;
};
export enum ArrayDiskStatus {
/** disabled, old disk still present */
DISK_DSBL = 'DISK_DSBL',
@@ -223,6 +230,49 @@ export enum ArrayDiskType {
PARITY = 'Parity'
}
export type ArrayMutations = {
__typename?: 'ArrayMutations';
/** Add new disk to array */
addDiskToArray?: Maybe<ArrayType>;
clearArrayDiskStatistics?: Maybe<Scalars['JSON']['output']>;
mountArrayDisk?: Maybe<Disk>;
/** Remove existing disk from array. NOTE: The array must be stopped before running this otherwise it'll throw an error. */
removeDiskFromArray?: Maybe<ArrayType>;
/** Set array state */
setState?: Maybe<ArrayType>;
unmountArrayDisk?: Maybe<Disk>;
};
export type ArrayMutationsaddDiskToArrayArgs = {
input?: InputMaybe<ArrayDiskInput>;
};
export type ArrayMutationsclearArrayDiskStatisticsArgs = {
id: Scalars['ID']['input'];
};
export type ArrayMutationsmountArrayDiskArgs = {
id: Scalars['ID']['input'];
};
export type ArrayMutationsremoveDiskFromArrayArgs = {
input?: InputMaybe<ArrayDiskInput>;
};
export type ArrayMutationssetStateArgs = {
input?: InputMaybe<ArrayStateInput>;
};
export type ArrayMutationsunmountArrayDiskArgs = {
id: Scalars['ID']['input'];
};
export enum ArrayPendingState {
/** Array has no data disks */
NO_DATA_DISKS = 'no_data_disks',
@@ -259,6 +309,18 @@ export enum ArrayState {
TOO_MANY_MISSING_DISKS = 'TOO_MANY_MISSING_DISKS'
}
export type ArrayStateInput = {
/** Array state */
desiredState: ArrayStateInputState;
};
export enum ArrayStateInputState {
/** Start array */
START = 'START',
/** Stop array */
STOP = 'STOP'
}
export type Baseboard = {
__typename?: 'Baseboard';
assetTag?: Maybe<Scalars['String']['output']>;
@@ -493,6 +555,7 @@ export type Docker = Node & {
__typename?: 'Docker';
containers?: Maybe<Array<DockerContainer>>;
id: Scalars['ID']['output'];
mutations: DockerMutations;
networks?: Maybe<Array<DockerNetwork>>;
};
@@ -516,6 +579,22 @@ export type DockerContainer = {
status: Scalars['String']['output'];
};
export type DockerMutations = {
__typename?: 'DockerMutations';
startContainer: DockerContainer;
stopContainer: DockerContainer;
};
export type DockerMutationsstartContainerArgs = {
id: Scalars['ID']['input'];
};
export type DockerMutationsstopContainerArgs = {
id: Scalars['ID']['input'];
};
export type DockerNetwork = {
__typename?: 'DockerNetwork';
attachable: Scalars['Boolean']['output'];
@@ -665,6 +744,8 @@ export type LogFileContent = {
content: Scalars['String']['output'];
/** Path to the log file */
path: Scalars['String']['output'];
/** Starting line number of the content (1-indexed) */
startLine?: Maybe<Scalars['Int']['output']>;
/** Total number of lines in the file */
totalLines: Scalars['Int']['output'];
};
@@ -729,8 +810,6 @@ export type Mount = {
export type Mutation = {
__typename?: 'Mutation';
/** Add new disk to array */
addDiskToArray?: Maybe<ArrayType>;
addPermission: Scalars['Boolean']['output'];
addRoleForApiKey: Scalars['Boolean']['output'];
addRoleForUser: Scalars['Boolean']['output'];
@@ -740,9 +819,9 @@ export type Mutation = {
/** Marks a notification as archived. */
archiveNotification: Notification;
archiveNotifications: NotificationOverview;
array?: Maybe<ArrayMutations>;
/** Cancel parity check */
cancelParityCheck?: Maybe<Scalars['JSON']['output']>;
clearArrayDiskStatistics?: Maybe<Scalars['JSON']['output']>;
connectSignIn: Scalars['Boolean']['output'];
connectSignOut: Scalars['Boolean']['output'];
createApiKey: ApiKeyWithSecret;
@@ -754,29 +833,21 @@ export type Mutation = {
deleteUser?: Maybe<User>;
enableDynamicRemoteAccess: Scalars['Boolean']['output'];
login?: Maybe<Scalars['String']['output']>;
mountArrayDisk?: Maybe<Disk>;
/** Pause parity check */
pauseParityCheck?: Maybe<Scalars['JSON']['output']>;
reboot?: Maybe<Scalars['String']['output']>;
/** Reads each notification to recompute & update the overview. */
recalculateOverview: NotificationOverview;
/** Remove existing disk from array. NOTE: The array must be stopped before running this otherwise it'll throw an error. */
removeDiskFromArray?: Maybe<ArrayType>;
removeRoleFromApiKey: Scalars['Boolean']['output'];
/** Resume parity check */
resumeParityCheck?: Maybe<Scalars['JSON']['output']>;
setAdditionalAllowedOrigins: Array<Scalars['String']['output']>;
setupRemoteAccess: Scalars['Boolean']['output'];
shutdown?: Maybe<Scalars['String']['output']>;
/** Start array */
startArray?: Maybe<ArrayType>;
/** Start parity check */
startParityCheck?: Maybe<Scalars['JSON']['output']>;
/** Stop array */
stopArray?: Maybe<ArrayType>;
unarchiveAll: NotificationOverview;
unarchiveNotifications: NotificationOverview;
unmountArrayDisk?: Maybe<Disk>;
/** Marks a notification as unread. */
unreadNotification: Notification;
/**
@@ -787,11 +858,6 @@ export type Mutation = {
};
export type MutationaddDiskToArrayArgs = {
input?: InputMaybe<arrayDiskInput>;
};
export type MutationaddPermissionArgs = {
input: AddPermissionInput;
};
@@ -827,11 +893,6 @@ export type MutationarchiveNotificationsArgs = {
};
export type MutationclearArrayDiskStatisticsArgs = {
id: Scalars['ID']['input'];
};
export type MutationconnectSignInArgs = {
input: ConnectSignInInput;
};
@@ -869,16 +930,6 @@ export type MutationloginArgs = {
};
export type MutationmountArrayDiskArgs = {
id: Scalars['ID']['input'];
};
export type MutationremoveDiskFromArrayArgs = {
input?: InputMaybe<arrayDiskInput>;
};
export type MutationremoveRoleFromApiKeyArgs = {
input: RemoveRoleFromApiKeyInput;
};
@@ -909,11 +960,6 @@ export type MutationunarchiveNotificationsArgs = {
};
export type MutationunmountArrayDiskArgs = {
id: Scalars['ID']['input'];
};
export type MutationunreadNotificationArgs = {
id: Scalars['String']['input'];
};
@@ -1156,6 +1202,7 @@ export type Query = {
* Get the content of a specific log file
* @param path Path to the log file
* @param lines Number of lines to read from the end of the file (default: 100)
* @param startLine Optional starting line number (1-indexed)
*/
logFile: LogFileContent;
/** List all available log files */
@@ -1213,6 +1260,7 @@ export type QuerydockerNetworksArgs = {
export type QuerylogFileArgs = {
lines?: InputMaybe<Scalars['Int']['input']>;
path: Scalars['String']['input'];
startLine?: InputMaybe<Scalars['Int']['input']>;
};
@@ -1819,13 +1867,6 @@ export type addUserInput = {
password: Scalars['String']['input'];
};
export type arrayDiskInput = {
/** Disk ID */
id: Scalars['ID']['input'];
/** The slot for the disk */
slot?: InputMaybe<Scalars['Int']['input']>;
};
export type deleteUserInput = {
name: Scalars['String']['input'];
};
@@ -1941,10 +1982,14 @@ export type ResolversTypes = ResolversObject<{
ArrayCapacity: ResolverTypeWrapper<ArrayCapacity>;
ArrayDisk: ResolverTypeWrapper<ArrayDisk>;
ArrayDiskFsColor: ArrayDiskFsColor;
ArrayDiskInput: ArrayDiskInput;
ArrayDiskStatus: ArrayDiskStatus;
ArrayDiskType: ArrayDiskType;
ArrayMutations: ResolverTypeWrapper<ArrayMutations>;
ArrayPendingState: ArrayPendingState;
ArrayState: ArrayState;
ArrayStateInput: ArrayStateInput;
ArrayStateInputState: ArrayStateInputState;
Baseboard: ResolverTypeWrapper<Baseboard>;
Boolean: ResolverTypeWrapper<Scalars['Boolean']['output']>;
Capacity: ResolverTypeWrapper<Capacity>;
@@ -1974,6 +2019,7 @@ export type ResolversTypes = ResolversObject<{
Display: ResolverTypeWrapper<Display>;
Docker: ResolverTypeWrapper<Docker>;
DockerContainer: ResolverTypeWrapper<DockerContainer>;
DockerMutations: ResolverTypeWrapper<DockerMutations>;
DockerNetwork: ResolverTypeWrapper<DockerNetwork>;
DynamicRemoteAccessStatus: ResolverTypeWrapper<DynamicRemoteAccessStatus>;
DynamicRemoteAccessType: DynamicRemoteAccessType;
@@ -2053,7 +2099,6 @@ export type ResolversTypes = ResolversObject<{
WAN_FORWARD_TYPE: WAN_FORWARD_TYPE;
Welcome: ResolverTypeWrapper<Welcome>;
addUserInput: addUserInput;
arrayDiskInput: arrayDiskInput;
deleteUserInput: deleteUserInput;
mdState: mdState;
registrationType: registrationType;
@@ -2075,6 +2120,9 @@ export type ResolversParentTypes = ResolversObject<{
Array: ArrayType;
ArrayCapacity: ArrayCapacity;
ArrayDisk: ArrayDisk;
ArrayDiskInput: ArrayDiskInput;
ArrayMutations: ArrayMutations;
ArrayStateInput: ArrayStateInput;
Baseboard: Baseboard;
Boolean: Scalars['Boolean']['output'];
Capacity: Capacity;
@@ -2098,6 +2146,7 @@ export type ResolversParentTypes = ResolversObject<{
Display: Display;
Docker: Docker;
DockerContainer: DockerContainer;
DockerMutations: DockerMutations;
DockerNetwork: DockerNetwork;
DynamicRemoteAccessStatus: DynamicRemoteAccessStatus;
EnableDynamicRemoteAccessInput: EnableDynamicRemoteAccessInput;
@@ -2161,7 +2210,6 @@ export type ResolversParentTypes = ResolversObject<{
Vms: Vms;
Welcome: Welcome;
addUserInput: addUserInput;
arrayDiskInput: arrayDiskInput;
deleteUserInput: deleteUserInput;
usersInput: usersInput;
}>;
@@ -2246,6 +2294,16 @@ export type ArrayDiskResolvers<ContextType = Context, ParentType extends Resolve
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
}>;
export type ArrayMutationsResolvers<ContextType = Context, ParentType extends ResolversParentTypes['ArrayMutations'] = ResolversParentTypes['ArrayMutations']> = ResolversObject<{
addDiskToArray?: Resolver<Maybe<ResolversTypes['Array']>, ParentType, ContextType, Partial<ArrayMutationsaddDiskToArrayArgs>>;
clearArrayDiskStatistics?: Resolver<Maybe<ResolversTypes['JSON']>, ParentType, ContextType, RequireFields<ArrayMutationsclearArrayDiskStatisticsArgs, 'id'>>;
mountArrayDisk?: Resolver<Maybe<ResolversTypes['Disk']>, ParentType, ContextType, RequireFields<ArrayMutationsmountArrayDiskArgs, 'id'>>;
removeDiskFromArray?: Resolver<Maybe<ResolversTypes['Array']>, ParentType, ContextType, Partial<ArrayMutationsremoveDiskFromArrayArgs>>;
setState?: Resolver<Maybe<ResolversTypes['Array']>, ParentType, ContextType, Partial<ArrayMutationssetStateArgs>>;
unmountArrayDisk?: Resolver<Maybe<ResolversTypes['Disk']>, ParentType, ContextType, RequireFields<ArrayMutationsunmountArrayDiskArgs, 'id'>>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
}>;
export type BaseboardResolvers<ContextType = Context, ParentType extends ResolversParentTypes['Baseboard'] = ResolversParentTypes['Baseboard']> = ResolversObject<{
assetTag?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
manufacturer?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
@@ -2413,6 +2471,7 @@ export type DisplayResolvers<ContextType = Context, ParentType extends Resolvers
export type DockerResolvers<ContextType = Context, ParentType extends ResolversParentTypes['Docker'] = ResolversParentTypes['Docker']> = ResolversObject<{
containers?: Resolver<Maybe<Array<ResolversTypes['DockerContainer']>>, ParentType, ContextType>;
id?: Resolver<ResolversTypes['ID'], ParentType, ContextType>;
mutations?: Resolver<ResolversTypes['DockerMutations'], ParentType, ContextType>;
networks?: Resolver<Maybe<Array<ResolversTypes['DockerNetwork']>>, ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
}>;
@@ -2436,6 +2495,12 @@ export type DockerContainerResolvers<ContextType = Context, ParentType extends R
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
}>;
export type DockerMutationsResolvers<ContextType = Context, ParentType extends ResolversParentTypes['DockerMutations'] = ResolversParentTypes['DockerMutations']> = ResolversObject<{
startContainer?: Resolver<ResolversTypes['DockerContainer'], ParentType, ContextType, RequireFields<DockerMutationsstartContainerArgs, 'id'>>;
stopContainer?: Resolver<ResolversTypes['DockerContainer'], ParentType, ContextType, RequireFields<DockerMutationsstopContainerArgs, 'id'>>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
}>;
export type DockerNetworkResolvers<ContextType = Context, ParentType extends ResolversParentTypes['DockerNetwork'] = ResolversParentTypes['DockerNetwork']> = ResolversObject<{
attachable?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>;
configFrom?: Resolver<Maybe<ResolversTypes['JSON']>, ParentType, ContextType>;
@@ -2559,6 +2624,7 @@ export type LogFileResolvers<ContextType = Context, ParentType extends Resolvers
export type LogFileContentResolvers<ContextType = Context, ParentType extends ResolversParentTypes['LogFileContent'] = ResolversParentTypes['LogFileContent']> = ResolversObject<{
content?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
path?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
startLine?: Resolver<Maybe<ResolversTypes['Int']>, ParentType, ContextType>;
totalLines?: Resolver<ResolversTypes['Int'], ParentType, ContextType>;
__isTypeOf?: IsTypeOfResolverFn<ParentType, ContextType>;
}>;
@@ -2607,7 +2673,6 @@ export type MountResolvers<ContextType = Context, ParentType extends ResolversPa
}>;
export type MutationResolvers<ContextType = Context, ParentType extends ResolversParentTypes['Mutation'] = ResolversParentTypes['Mutation']> = ResolversObject<{
addDiskToArray?: Resolver<Maybe<ResolversTypes['Array']>, ParentType, ContextType, Partial<MutationaddDiskToArrayArgs>>;
addPermission?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType, RequireFields<MutationaddPermissionArgs, 'input'>>;
addRoleForApiKey?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType, RequireFields<MutationaddRoleForApiKeyArgs, 'input'>>;
addRoleForUser?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType, RequireFields<MutationaddRoleForUserArgs, 'input'>>;
@@ -2615,8 +2680,8 @@ export type MutationResolvers<ContextType = Context, ParentType extends Resolver
archiveAll?: Resolver<ResolversTypes['NotificationOverview'], ParentType, ContextType, Partial<MutationarchiveAllArgs>>;
archiveNotification?: Resolver<ResolversTypes['Notification'], ParentType, ContextType, RequireFields<MutationarchiveNotificationArgs, 'id'>>;
archiveNotifications?: Resolver<ResolversTypes['NotificationOverview'], ParentType, ContextType, Partial<MutationarchiveNotificationsArgs>>;
array?: Resolver<Maybe<ResolversTypes['ArrayMutations']>, ParentType, ContextType>;
cancelParityCheck?: Resolver<Maybe<ResolversTypes['JSON']>, ParentType, ContextType>;
clearArrayDiskStatistics?: Resolver<Maybe<ResolversTypes['JSON']>, ParentType, ContextType, RequireFields<MutationclearArrayDiskStatisticsArgs, 'id'>>;
connectSignIn?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType, RequireFields<MutationconnectSignInArgs, 'input'>>;
connectSignOut?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType>;
createApiKey?: Resolver<ResolversTypes['ApiKeyWithSecret'], ParentType, ContextType, RequireFields<MutationcreateApiKeyArgs, 'input'>>;
@@ -2626,22 +2691,17 @@ export type MutationResolvers<ContextType = Context, ParentType extends Resolver
deleteUser?: Resolver<Maybe<ResolversTypes['User']>, ParentType, ContextType, RequireFields<MutationdeleteUserArgs, 'input'>>;
enableDynamicRemoteAccess?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType, RequireFields<MutationenableDynamicRemoteAccessArgs, 'input'>>;
login?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType, RequireFields<MutationloginArgs, 'password' | 'username'>>;
mountArrayDisk?: Resolver<Maybe<ResolversTypes['Disk']>, ParentType, ContextType, RequireFields<MutationmountArrayDiskArgs, 'id'>>;
pauseParityCheck?: Resolver<Maybe<ResolversTypes['JSON']>, ParentType, ContextType>;
reboot?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
recalculateOverview?: Resolver<ResolversTypes['NotificationOverview'], ParentType, ContextType>;
removeDiskFromArray?: Resolver<Maybe<ResolversTypes['Array']>, ParentType, ContextType, Partial<MutationremoveDiskFromArrayArgs>>;
removeRoleFromApiKey?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType, RequireFields<MutationremoveRoleFromApiKeyArgs, 'input'>>;
resumeParityCheck?: Resolver<Maybe<ResolversTypes['JSON']>, ParentType, ContextType>;
setAdditionalAllowedOrigins?: Resolver<Array<ResolversTypes['String']>, ParentType, ContextType, RequireFields<MutationsetAdditionalAllowedOriginsArgs, 'input'>>;
setupRemoteAccess?: Resolver<ResolversTypes['Boolean'], ParentType, ContextType, RequireFields<MutationsetupRemoteAccessArgs, 'input'>>;
shutdown?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
startArray?: Resolver<Maybe<ResolversTypes['Array']>, ParentType, ContextType>;
startParityCheck?: Resolver<Maybe<ResolversTypes['JSON']>, ParentType, ContextType, Partial<MutationstartParityCheckArgs>>;
stopArray?: Resolver<Maybe<ResolversTypes['Array']>, ParentType, ContextType>;
unarchiveAll?: Resolver<ResolversTypes['NotificationOverview'], ParentType, ContextType, Partial<MutationunarchiveAllArgs>>;
unarchiveNotifications?: Resolver<ResolversTypes['NotificationOverview'], ParentType, ContextType, Partial<MutationunarchiveNotificationsArgs>>;
unmountArrayDisk?: Resolver<Maybe<ResolversTypes['Disk']>, ParentType, ContextType, RequireFields<MutationunmountArrayDiskArgs, 'id'>>;
unreadNotification?: Resolver<ResolversTypes['Notification'], ParentType, ContextType, RequireFields<MutationunreadNotificationArgs, 'id'>>;
updateApiSettings?: Resolver<ResolversTypes['ConnectSettingsValues'], ParentType, ContextType, RequireFields<MutationupdateApiSettingsArgs, 'input'>>;
}>;
@@ -3268,6 +3328,7 @@ export type Resolvers<ContextType = Context> = ResolversObject<{
Array?: ArrayResolvers<ContextType>;
ArrayCapacity?: ArrayCapacityResolvers<ContextType>;
ArrayDisk?: ArrayDiskResolvers<ContextType>;
ArrayMutations?: ArrayMutationsResolvers<ContextType>;
Baseboard?: BaseboardResolvers<ContextType>;
Capacity?: CapacityResolvers<ContextType>;
Case?: CaseResolvers<ContextType>;
@@ -3287,6 +3348,7 @@ export type Resolvers<ContextType = Context> = ResolversObject<{
Display?: DisplayResolvers<ContextType>;
Docker?: DockerResolvers<ContextType>;
DockerContainer?: DockerContainerResolvers<ContextType>;
DockerMutations?: DockerMutationsResolvers<ContextType>;
DockerNetwork?: DockerNetworkResolvers<ContextType>;
DynamicRemoteAccessStatus?: DynamicRemoteAccessStatusResolvers<ContextType>;
Flash?: FlashResolvers<ContextType>;

View File

@@ -2,7 +2,7 @@ import { mergeTypeDefs } from '@graphql-tools/merge';
import { logger } from '@app/core/log.js';
export const loadTypeDefs = async () => {
export const loadTypeDefs = async (additionalTypeDefs: string[] = []) => {
// TypeScript now knows this returns Record<string, () => Promise<string>>
const typeModules = import.meta.glob('./types/**/*.graphql', { query: '?raw', import: 'default' });
@@ -19,6 +19,7 @@ export const loadTypeDefs = async () => {
if (!files.length) {
throw new Error('No GraphQL type definitions found');
}
files.push(...additionalTypeDefs);
return mergeTypeDefs(files);
} catch (error) {
logger.error('Failed to load GraphQL type definitions:', error);

View File

@@ -3,16 +3,26 @@ type Query {
array: Array!
}
type Mutation {
enum ArrayStateInputState {
"""Start array"""
startArray: Array
START
"""Stop array"""
stopArray: Array
STOP
}
input ArrayStateInput {
"""Array state"""
desiredState: ArrayStateInputState!
}
type ArrayMutations {
"""Set array state"""
setState(input: ArrayStateInput): Array
"""Add new disk to array"""
addDiskToArray(input: arrayDiskInput): Array
addDiskToArray(input: ArrayDiskInput): Array
"""Remove existing disk from array. NOTE: The array must be stopped before running this otherwise it'll throw an error."""
removeDiskFromArray(input: arrayDiskInput): Array
removeDiskFromArray(input: ArrayDiskInput): Array
mountArrayDisk(id: ID!): Disk
unmountArrayDisk(id: ID!): Disk
@@ -20,11 +30,15 @@ type Mutation {
clearArrayDiskStatistics(id: ID!): JSON
}
type Mutation {
array: ArrayMutations
}
type Subscription {
array: Array!
}
input arrayDiskInput {
input ArrayDiskInput {
"""Disk ID"""
id: ID!
"""The slot for the disk"""

View File

@@ -0,0 +1,43 @@
type ApiKeyResponse {
valid: Boolean!
error: String
}
enum MinigraphStatus {
PRE_INIT
CONNECTING
CONNECTED
PING_FAILURE
ERROR_RETRYING
}
type MinigraphqlResponse {
status: MinigraphStatus!
timeout: Int
error: String
}
type CloudResponse {
status: String!
ip: String
error: String
}
type RelayResponse {
status: String!
timeout: String
error: String
}
type Cloud {
error: String
apiKey: ApiKeyResponse!
relay: RelayResponse
minigraphql: MinigraphqlResponse!
cloud: CloudResponse!
allowedOrigins: [String!]!
}
type Query {
cloud: Cloud
}

View File

@@ -0,0 +1,60 @@
type Query {
"""All Docker containers"""
dockerContainers(all: Boolean): [DockerContainer!]!
}
type Subscription {
dockerContainer(id: ID!): DockerContainer!
dockerContainers: [DockerContainer]
}
enum ContainerPortType {
TCP
UDP
}
type ContainerPort {
ip: String
privatePort: Int
publicPort: Int
type: ContainerPortType
}
enum ContainerState {
RUNNING
EXITED
}
type ContainerHostConfig {
networkMode: String!
}
type ContainerMount {
type: String!
name: String!
source: String!
destination: String!
driver: String!
mode: String!
rw: Boolean!
propagation: String!
}
type DockerContainer {
id: ID!
names: [String!]
image: String!
imageId: String!
command: String!
created: Int!
ports: [ContainerPort!]!
""" (B) Total size of all the files in the container """
sizeRootFs: Long
labels: JSON
state: ContainerState!
status: String!
hostConfig: ContainerHostConfig
networkSettings: JSON
mounts: [JSON]
autoStart: Boolean!
}

View File

@@ -6,4 +6,13 @@ type Docker implements Node {
type Query {
docker: Docker!
}
type DockerMutations {
startContainer(id: ID!): DockerContainer!
stopContainer(id: ID!): DockerContainer!
}
extend type Docker {
mutations: DockerMutations!
}

View File

@@ -0,0 +1,13 @@
type Query {
flash: Flash
}
type Subscription {
flash: Flash!
}
type Flash {
guid: String
vendor: String
product: String
}

View File

@@ -0,0 +1,11 @@
type Info {
"""Count of docker containers"""
apps: InfoApps
}
type InfoApps {
"""How many docker containers are installed"""
installed: Int
"""How many docker containers are running"""
started: Int
}

View File

@@ -0,0 +1,14 @@
type Info {
baseboard: Baseboard
}
type Baseboard {
# Dell Inc.
manufacturer: String!
# 0MD99X
model: String
# A07
version: String
serial: String
assetTag: String
}

View File

@@ -0,0 +1,39 @@
type Info {
cpu: InfoCpu
}
type InfoCpu {
# 'Intel®'
manufacturer: String!
# 'Xeon® L5640'
brand: String!
# 'GenuineIntel'
vendor: String!
# '6'
family: String!
# '44'
model: String!
# '2'
stepping: Int!
# ''
revision: String!
# ''
voltage: String
# '2.27'
speed: Float!
# '1.60'
speedmin: Float!
# '2.26'
speedmax: Float!
# 12
threads: Int!
# 6
cores: Int!
# 1
processors: Long!
# 'LGA1366'
socket: String!
# { l1d: 196608, l1i: 196608, l2: 1, l3: 12 }
cache: JSON!
flags: [String!]
}

View File

@@ -0,0 +1,52 @@
type Info {
devices: Devices
}
type Devices {
gpu: [Gpu]
network: [Network]
pci: [Pci]
usb: [Usb]
}
type Gpu {
id: ID!
type: String!
typeid: String!
vendorname: String!
productid: String!
blacklisted: Boolean!
class: String!
}
type Network {
iface: String
ifaceName: String
ipv4: String
ipv6: String
mac: String
internal: String
operstate: String
type: String
duplex: String
mtu: String
speed: String
carrierChanges: String
}
type Pci {
id: ID!
type: String
typeid: String
vendorname: String
vendorid: String
productname: String
productid: String
blacklisted: String
class: String
}
type Usb {
id: ID!
name: String
}

View File

@@ -0,0 +1,34 @@
type Info {
display: Display
}
type Display {
date: String
number: String
scale: Boolean
tabs: Boolean
users: String
resize: Boolean
wwn: Boolean
total: Boolean
usage: Boolean
banner: String
dashapps: String
theme: Theme
text: Boolean
unit: Temperature
warning: Int
critical: Int
hot: Int
max: Int
locale: String
}
enum Temperature {
C
F
}
enum Theme {
white
}

View File

@@ -0,0 +1,4 @@
type Info {
"""Machine ID"""
machineId: ID
}

View File

@@ -0,0 +1,41 @@
type Info {
memory: InfoMemory
}
type InfoMemory {
max: Long!
total: Long!
free: Long!
used: Long!
active: Long!
available: Long!
buffcache: Long!
swaptotal: Long!
swapused: Long!
swapfree: Long!
layout: [MemoryLayout!]
}
type MemoryLayout {
size: Long!
bank: String
type: MemoryType
clockSpeed: Long
formFactor: MemoryFormFactor
manufacturer: String
partNum: String
serialNum: String
voltageConfigured: Long
voltageMin: Long
voltageMax: Long
}
enum MemoryType {
DDR2
DDR3
DDR4
}
enum MemoryFormFactor {
DIMM
}

View File

@@ -0,0 +1,18 @@
type Info {
os: Os
}
type Os {
platform: String
distro: String
release: String
codename: String
kernel: String
arch: String
hostname: String
codepage: String
logofile: String
serial: String
build: String
uptime: DateTime
}

View File

@@ -0,0 +1,12 @@
type Info {
system: System
}
type System {
manufacturer: String
model: String
version: String
serial: String
uuid: String
sku: String
}

View File

@@ -0,0 +1,32 @@
type Info {
versions: Versions
}
type Versions {
kernel: String
openssl: String
systemOpenssl: String
systemOpensslLib: String
node: String
v8: String
npm: String
yarn: String
pm2: String
gulp: String
grunt: String
git: String
tsc: String
mysql: String
redis: String
mongodb: String
apache: String
nginx: String
php: String
docker: String
postfix: String
postgresql: String
perl: String
python: String
gcc: String
unraid: String
}

View File

@@ -0,0 +1,13 @@
type Query {
owner: Owner
}
type Subscription {
owner: Owner!
}
type Owner {
username: String
url: String
avatar: String
}

View File

@@ -0,0 +1,6 @@
type Mount {
name: String
directory: String
type: String
permissions: String
}

View File

@@ -0,0 +1,60 @@
type Partition {
devlinks: String
devname: String
devpath: String
devtype: String
idAta: String
idAtaDownloadMicrocode: String
idAtaFeatureSetAam: String
idAtaFeatureSetAamCurrentValue: String
idAtaFeatureSetAamEnabled: String
idAtaFeatureSetAamVendorRecommendedValue: String
idAtaFeatureSetApm: String
idAtaFeatureSetApmCurrentValue: String
idAtaFeatureSetApmEnabled: String
idAtaFeatureSetHpa: String
idAtaFeatureSetHpaEnabled: String
idAtaFeatureSetPm: String
idAtaFeatureSetPmEnabled: String
idAtaFeatureSetPuis: String
idAtaFeatureSetPuisEnabled: String
idAtaFeatureSetSecurity: String
idAtaFeatureSetSecurityEnabled: String
idAtaFeatureSetSecurityEnhancedEraseUnitMin: String
idAtaFeatureSetSecurityEraseUnitMin: String
idAtaFeatureSetSmart: String
idAtaFeatureSetSmartEnabled: String
idAtaRotationRateRpm: String
idAtaSata: String
idAtaSataSignalRateGen1: String
idAtaSataSignalRateGen2: String
idAtaWriteCache: String
idAtaWriteCacheEnabled: String
idBus: String
idFsType: String
idFsUsage: String
idFsUuid: String
idFsUuidEnc: String
idModel: String
idModelEnc: String
idPartEntryDisk: String
idPartEntryNumber: String
idPartEntryOffset: String
idPartEntryScheme: String
idPartEntrySize: String
idPartEntryType: String
idPartTableType: String
idPath: String
idPathTag: String
idRevision: String
idSerial: String
idSerialShort: String
idType: String
idWwn: String
idWwnWithExtension: String
major: String
minor: String
partn: String
subsystem: String
usecInitialized: String
}

View File

@@ -35,6 +35,7 @@ export const store = configureStore({
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
export type ApiStore = typeof store;
export const getters = {
cache: () => store.getState().cache,

View File

@@ -3,6 +3,7 @@ import { type IniStringBoolean, type IniStringBooleanOrAuto } from '@app/core/ty
import { toNumber } from '@app/core/utils/index.js';
import {
ArrayState,
ConfigErrorState,
DiskFsType,
RegistrationState,
registrationType,
@@ -23,7 +24,7 @@ export type VarIni = {
cacheSbNumDisks: string;
comment: string;
configValid: string;
configState: string;
configErrorState: string;
csrfToken: string;
defaultFormat: string;
defaultFsType: string;
@@ -200,6 +201,10 @@ const safeParseMdState = (mdState: string | undefined): ArrayState => {
return attemptedParse;
};
export const convertconfigErrorStateToEnum = (configErrorState: string): ConfigErrorState => {
return ConfigErrorState[configErrorState.toUpperCase()];
};
export const parse: StateFileToIniParserMap['var'] = (iniFile) => {
return {
...iniFile,
@@ -209,7 +214,9 @@ export const parse: StateFileToIniParserMap['var'] = (iniFile) => {
cacheNumDevices: toNumber(iniFile.cacheNumDevices),
cacheSbNumDisks: toNumber(iniFile.cacheSbNumDisks),
configValid: iniBooleanToJsBoolean(iniFile.configValid, false),
configState: iniFile.configValid,
configErrorState: iniBooleanToJsBoolean(iniFile.configValid, false)
? null
: convertconfigErrorStateToEnum(iniFile.configValid),
deviceCount: toNumber(iniFile.deviceCount),
fsCopyPrcnt: toNumber(iniFile.fsCopyPrcnt),
fsNumMounted: toNumber(iniFile.fsNumMounted),

View File

@@ -9,7 +9,6 @@ import { store } from '@app/store/index.js';
import { syncInfoApps } from '@app/store/sync/info-apps-sync.js';
import { syncRegistration } from '@app/store/sync/registration-sync.js';
import { FileLoadStatus } from '@app/store/types.js';
import { setupConfigPathWatch } from '@app/store/watch/config-watch.js';
export const startStoreSync = async () => {
// The last state is stored so we don't end up in a loop of writing -> reading -> writing
@@ -45,6 +44,4 @@ export const startStoreSync = async () => {
lastState = state;
});
setupConfigPathWatch();
};

View File

@@ -1,39 +0,0 @@
import { existsSync, writeFileSync } from 'fs';
import { watch } from 'chokidar';
import { logger } from '@app/core/log.js';
import { getWriteableConfig } from '@app/core/utils/files/config-file-normalizer.js';
import { safelySerializeObjectToIni } from '@app/core/utils/files/safe-ini-serializer.js';
import { CHOKIDAR_USEPOLLING, ENVIRONMENT } from '@app/environment.js';
import { getters, store } from '@app/store/index.js';
import { initialState, loadConfigFile, logoutUser } from '@app/store/modules/config.js';
export const setupConfigPathWatch = () => {
const myServersConfigPath = getters.paths()?.['myservers-config'];
if (myServersConfigPath) {
logger.info('Watch Setup on Config Path: %s', myServersConfigPath);
if (!existsSync(myServersConfigPath)) {
const config = safelySerializeObjectToIni(getWriteableConfig(initialState, 'flash'));
writeFileSync(myServersConfigPath, config, 'utf-8');
}
const watcher = watch(myServersConfigPath, {
persistent: true,
ignoreInitial: false,
usePolling: CHOKIDAR_USEPOLLING === true,
})
.on('change', async (change) => {
logger.trace('Config File Changed, Reloading Config %s', change);
await store.dispatch(loadConfigFile());
})
.on('unlink', async () => {
const config = safelySerializeObjectToIni(getWriteableConfig(initialState, 'flash'));
await writeFileSync(myServersConfigPath, config, 'utf-8');
watcher.close();
setupConfigPathWatch();
store.dispatch(logoutUser({ reason: 'Config File was Deleted' }));
});
} else {
logger.error('[FATAL] Failed to setup watch on My Servers Config (Could Not Read Config Path)');
}
};

View File

@@ -11,6 +11,7 @@ import { GraphqlAuthGuard } from '@app/unraid-api/auth/auth.guard.js';
import { AuthModule } from '@app/unraid-api/auth/auth.module.js';
import { CronModule } from '@app/unraid-api/cron/cron.module.js';
import { GraphModule } from '@app/unraid-api/graph/graph.module.js';
import { PluginModule } from '@app/unraid-api/plugin/plugin.module.js';
import { RestModule } from '@app/unraid-api/rest/rest.module.js';
import { UnraidFileModifierModule } from '@app/unraid-api/unraid-file-modifier/unraid-file-modifier.module.js';
@@ -46,6 +47,7 @@ import { UnraidFileModifierModule } from '@app/unraid-api/unraid-file-modifier/u
},
]),
UnraidFileModifierModule,
PluginModule.registerPlugins(),
],
controllers: [],
providers: [

View File

@@ -1,6 +1,6 @@
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import crypto from 'crypto';
import { readdir, readFile, writeFile } from 'fs/promises';
import { readdir, readFile, unlink, writeFile } from 'fs/promises';
import { join } from 'path';
import { watch } from 'chokidar';
@@ -23,6 +23,7 @@ import {
import { getters, store } from '@app/store/index.js';
import { setLocalApiKey } from '@app/store/modules/config.js';
import { FileLoadStatus } from '@app/store/types.js';
import { batchProcess } from '@app/utils.js';
@Injectable()
export class ApiKeyService implements OnModuleInit {
@@ -312,4 +313,36 @@ export class ApiKeyService implements OnModuleInit {
basePath: this.basePath,
};
}
/**
* Deletes API keys from the disk and updates the in-memory store.
*
* This method first verifies that all the provided API key IDs exist in the in-memory store.
* If any keys are missing, it throws an Error detailing the missing keys.
* It then deletes the corresponding JSON files concurrently using batch processing.
* If any errors occur during the file deletion process, an array of errors is thrown.
*
* @param ids An array of API key identifiers to delete.
* @throws Error if one or more API keys are not found.
* @throws Array<Error> if errors occur during the file deletion.
*/
public async deleteApiKeys(ids: string[]): Promise<void> {
// First verify all keys exist
const missingKeys = ids.filter((id) => !this.findByField('id', id));
if (missingKeys.length > 0) {
throw new Error(`API keys not found: ${missingKeys.join(', ')}`);
}
// Delete all files in parallel
const { errors, data: deletedIds } = await batchProcess(ids, async (id) => {
await unlink(join(this.basePath, `${id}.json`));
return id;
});
const deletedSet = new Set(deletedIds);
this.memoryApiKeys = this.memoryApiKeys.filter((key) => !deletedSet.has(key.id));
if (errors.length > 0) {
throw errors;
}
}
}

View File

@@ -2,14 +2,17 @@ import { AuthActionVerb } from 'nest-authz';
import { Command, CommandRunner, InquirerService, Option } from 'nest-commander';
import type { Permission } from '@app/graphql/generated/api/types.js';
import type { DeleteApiKeyAnswers } from '@app/unraid-api/cli/apikey/delete-api-key.questions.js';
import { Resource, Role } from '@app/graphql/generated/api/types.js';
import { ApiKeyService } from '@app/unraid-api/auth/api-key.service.js';
import { AddApiKeyQuestionSet } from '@app/unraid-api/cli/apikey/add-api-key.questions.js';
import { DeleteApiKeyQuestionSet } from '@app/unraid-api/cli/apikey/delete-api-key.questions.js';
import { LogService } from '@app/unraid-api/cli/log.service.js';
interface KeyOptions {
name: string;
create: boolean;
delete?: boolean;
description?: string;
roles?: Role[];
permissions?: Permission[];
@@ -17,7 +20,7 @@ interface KeyOptions {
@Command({
name: 'apikey',
description: `Create / Fetch Connect API Keys - use --create with no arguments for a creation wizard`,
description: `Create / Fetch / Delete Connect API Keys - use --create with no arguments for a creation wizard, or --delete to remove keys`,
})
export class ApiKeyCommand extends CommandRunner {
constructor(
@@ -88,8 +91,50 @@ ACTIONS: ${Object.values(AuthActionVerb).join(', ')}`,
return description;
}
async run(_: string[], options: KeyOptions = { create: false, name: '' }): Promise<void> {
@Option({
flags: '--delete',
description: 'Delete selected API keys',
})
parseDelete(): boolean {
return true;
}
/** Prompt the user to select API keys to delete. Then, delete the selected keys. */
private async deleteKeys() {
const allKeys = this.apiKeyService.findAll();
if (allKeys.length === 0) {
this.logger.log('No API keys found to delete');
return;
}
const answers = await this.inquirerService.prompt<DeleteApiKeyAnswers>(
DeleteApiKeyQuestionSet.name,
{}
);
if (!answers.selectedKeys || answers.selectedKeys.length === 0) {
this.logger.log('No keys selected for deletion');
return;
}
try {
await this.apiKeyService.deleteApiKeys(answers.selectedKeys);
this.logger.log(`Successfully deleted ${answers.selectedKeys.length} API keys`);
} catch (error) {
this.logger.error(error as any);
process.exit(1);
}
}
async run(
_: string[],
options: KeyOptions = { create: false, name: '', delete: false }
): Promise<void> {
try {
if (options.delete) {
await this.deleteKeys();
return;
}
const key = this.apiKeyService.findByField('name', options.name);
if (key) {
this.logger.log(key.key);

View File

@@ -0,0 +1,35 @@
import { ChoicesFor, Question, QuestionSet } from 'nest-commander';
import { ApiKeyService } from '@app/unraid-api/auth/api-key.service.js';
import { LogService } from '@app/unraid-api/cli/log.service.js';
export interface DeleteApiKeyAnswers {
selectedKeys: string[];
}
@QuestionSet({ name: 'delete-api-key' })
export class DeleteApiKeyQuestionSet {
constructor(
private readonly apiKeyService: ApiKeyService,
private readonly logger: LogService
) {}
static name = 'delete-api-key';
@Question({
name: 'selectedKeys',
type: 'checkbox',
message: 'Select API keys to delete:',
})
parseSelectedKeys(keyIds: string[]): string[] {
return keyIds;
}
@ChoicesFor({ name: 'selectedKeys' })
async getKeys() {
return this.apiKeyService.findAll().map((key) => ({
name: `${key.name} (${key.description ?? ''}) [${key.id}]`,
value: key.id,
}));
}
}

View File

@@ -1,8 +1,11 @@
import { Module } from '@nestjs/common';
import { DynamicModule, Module, Provider, Type } from '@nestjs/common';
import { CommandRunner } from 'nest-commander';
import { ApiKeyService } from '@app/unraid-api/auth/api-key.service.js';
import { AddApiKeyQuestionSet } from '@app/unraid-api/cli/apikey/add-api-key.questions.js';
import { ApiKeyCommand } from '@app/unraid-api/cli/apikey/api-key.command.js';
import { DeleteApiKeyQuestionSet } from '@app/unraid-api/cli/apikey/delete-api-key.questions.js';
import { ConfigCommand } from '@app/unraid-api/cli/config.command.js';
import { DeveloperCommand } from '@app/unraid-api/cli/developer/developer.command.js';
import { DeveloperQuestions } from '@app/unraid-api/cli/developer/developer.questions.js';
@@ -23,32 +26,77 @@ import { StatusCommand } from '@app/unraid-api/cli/status.command.js';
import { StopCommand } from '@app/unraid-api/cli/stop.command.js';
import { SwitchEnvCommand } from '@app/unraid-api/cli/switch-env.command.js';
import { VersionCommand } from '@app/unraid-api/cli/version.command.js';
import { ApiPluginDefinition } from '@app/unraid-api/plugin/plugin.interface.js';
import { PluginModule } from '@app/unraid-api/plugin/plugin.module.js';
import { PluginService } from '@app/unraid-api/plugin/plugin.service.js';
const DEFAULT_COMMANDS = [
ApiKeyCommand,
ConfigCommand,
DeveloperCommand,
LogsCommand,
ReportCommand,
RestartCommand,
StartCommand,
StatusCommand,
StopCommand,
SwitchEnvCommand,
VersionCommand,
SSOCommand,
ValidateTokenCommand,
AddSSOUserCommand,
RemoveSSOUserCommand,
ListSSOUserCommand,
] as const;
const DEFAULT_PROVIDERS = [
AddApiKeyQuestionSet,
DeleteApiKeyQuestionSet,
AddSSOUserQuestionSet,
RemoveSSOUserQuestionSet,
DeveloperQuestions,
LogService,
PM2Service,
ApiKeyService,
] as const;
type PluginProvider = Provider & {
provide: string | symbol | Type<any>;
useValue?: ApiPluginDefinition;
};
@Module({
providers: [
AddSSOUserCommand,
AddSSOUserQuestionSet,
RemoveSSOUserCommand,
RemoveSSOUserQuestionSet,
ListSSOUserCommand,
LogService,
PM2Service,
StartCommand,
StopCommand,
RestartCommand,
ReportCommand,
ApiKeyService,
ApiKeyCommand,
AddApiKeyQuestionSet,
SwitchEnvCommand,
VersionCommand,
StatusCommand,
SSOCommand,
ValidateTokenCommand,
LogsCommand,
ConfigCommand,
DeveloperCommand,
DeveloperQuestions,
],
imports: [PluginModule],
providers: [...DEFAULT_COMMANDS, ...DEFAULT_PROVIDERS],
})
export class CliModule {}
export class CliModule {
/**
* Get all registered commands
* @returns Array of registered command classes
*/
static getCommands(): Type<CommandRunner>[] {
return [...DEFAULT_COMMANDS];
}
/**
* Register the module with plugin support
* @returns DynamicModule configuration including plugin commands
*/
static async registerWithPlugins(): Promise<DynamicModule> {
const pluginModule = await PluginModule.registerPlugins();
// Get commands from plugins
const pluginCommands: Type<CommandRunner>[] = [];
for (const provider of (pluginModule.providers || []) as PluginProvider[]) {
if (provider.provide !== PluginService && provider.useValue?.commands) {
pluginCommands.push(...provider.useValue.commands);
}
}
return {
module: CliModule,
imports: [pluginModule],
providers: [...DEFAULT_COMMANDS, ...DEFAULT_PROVIDERS, ...pluginCommands],
};
}
}

View File

@@ -6,7 +6,8 @@ import { loadConfigFile, updateUserConfig } from '@app/store/modules/config.js';
import { writeConfigSync } from '@app/store/sync/config-disk-sync.js';
import { DeveloperQuestions } from '@app/unraid-api/cli/developer/developer.questions.js';
import { LogService } from '@app/unraid-api/cli/log.service.js';
import { RestartCommand } from '@app/unraid-api/cli/restart.command.js';
import { StartCommand } from '@app/unraid-api/cli/start.command.js';
import { StopCommand } from '@app/unraid-api/cli/stop.command.js';
interface DeveloperOptions {
disclaimer: boolean;
@@ -21,7 +22,8 @@ export class DeveloperCommand extends CommandRunner {
constructor(
private logger: LogService,
private readonly inquirerService: InquirerService,
private readonly restartCommand: RestartCommand
private readonly startCommand: StartCommand,
private readonly stopCommand: StopCommand
) {
super();
}
@@ -33,6 +35,7 @@ export class DeveloperCommand extends CommandRunner {
}
const { store } = await import('@app/store/index.js');
await store.dispatch(loadConfigFile());
await this.stopCommand.run([]);
store.dispatch(updateUserConfig({ local: { sandbox: options.sandbox ? 'yes' : 'no' } }));
writeConfigSync('flash');
@@ -40,6 +43,6 @@ export class DeveloperCommand extends CommandRunner {
'Updated Developer Configuration - restart the API in 5 seconds to apply them...'
);
await new Promise((resolve) => setTimeout(resolve, 5000));
await this.restartCommand.run([]);
await this.startCommand.run([], {});
}
}

View File

@@ -9,6 +9,8 @@ import { writeConfigSync } from '@app/store/sync/config-disk-sync.js';
import { LogService } from '@app/unraid-api/cli/log.service.js';
import { RestartCommand } from '@app/unraid-api/cli/restart.command.js';
import { AddSSOUserQuestionSet } from '@app/unraid-api/cli/sso/add-sso-user.questions.js';
import { StartCommand } from '@app/unraid-api/cli/start.command.js';
import { StopCommand } from '@app/unraid-api/cli/stop.command.js';
interface AddSSOUserCommandOptions {
disclaimer: string;
@@ -25,7 +27,8 @@ export class AddSSOUserCommand extends CommandRunner {
constructor(
private readonly logger: LogService,
private readonly inquirerService: InquirerService,
private readonly restartCommand: RestartCommand
private readonly startCommand: StartCommand,
private readonly stopCommand: StopCommand
) {
super();
}
@@ -34,16 +37,12 @@ export class AddSSOUserCommand extends CommandRunner {
try {
options = await this.inquirerService.prompt(AddSSOUserQuestionSet.name, options);
if (options.disclaimer === 'y' && options.username) {
await this.stopCommand.run([]);
await store.dispatch(loadConfigFile());
const shouldRestart = store.getState().config.remote.ssoSubIds.length === 0;
store.dispatch(addSsoUser(options.username));
writeConfigSync('flash');
this.logger.info(`User added ${options.username}`);
if (shouldRestart) {
this.logger.info('Restarting the Unraid API in 5 seconds to enable the SSO button');
await new Promise((resolve) => setTimeout(resolve, 5000));
await this.restartCommand.run([]);
}
this.logger.info(`User added ${options.username}, starting the API`);
await this.startCommand.run([], {});
}
} catch (e: unknown) {
if (e instanceof Error) {

View File

@@ -1,12 +1,14 @@
import { Injectable } from '@nestjs/common';
import { CommandRunner, InquirerService, Option, OptionChoiceFor, SubCommand } from 'nest-commander';
import { CommandRunner, InquirerService, Option, SubCommand } from 'nest-commander';
import { store } from '@app/store/index.js';
import { loadConfigFile, removeSsoUser } from '@app/store/modules/config.js';
import { writeConfigSync } from '@app/store/sync/config-disk-sync.js';
import { LogService } from '@app/unraid-api/cli/log.service.js';
import { RemoveSSOUserQuestionSet } from '@app/unraid-api/cli/sso/remove-sso-user.questions.js';
import { StartCommand } from '@app/unraid-api/cli/start.command.js';
import { StopCommand } from '@app/unraid-api/cli/stop.command.js';
interface RemoveSSOUserCommandOptions {
username: string;
@@ -21,13 +23,17 @@ interface RemoveSSOUserCommandOptions {
export class RemoveSSOUserCommand extends CommandRunner {
constructor(
private readonly logger: LogService,
private readonly inquirerService: InquirerService
private readonly inquirerService: InquirerService,
private readonly stopCommand: StopCommand,
private readonly startCommand: StartCommand
) {
super();
}
public async run(_input: string[], options: RemoveSSOUserCommandOptions): Promise<void> {
await store.dispatch(loadConfigFile());
options = await this.inquirerService.prompt(RemoveSSOUserQuestionSet.name, options);
await this.stopCommand.run([]);
store.dispatch(removeSsoUser(options.username === 'all' ? null : options.username));
if (options.username === 'all') {
this.logger.info('All users removed from SSO');
@@ -35,6 +41,7 @@ export class RemoveSSOUserCommand extends CommandRunner {
this.logger.info('User removed: ' + options.username);
}
writeConfigSync('flash');
await this.startCommand.run([], {});
}
@Option({

View File

@@ -24,38 +24,46 @@ import { ResolversModule } from '@app/unraid-api/graph/resolvers/resolvers.modul
import { sandboxPlugin } from '@app/unraid-api/graph/sandbox-plugin.js';
import { ServicesResolver } from '@app/unraid-api/graph/services/services.resolver.js';
import { SharesResolver } from '@app/unraid-api/graph/shares/shares.resolver.js';
import { PluginModule } from '@app/unraid-api/plugin/plugin.module.js';
import { PluginService } from '@app/unraid-api/plugin/plugin.service.js';
@Module({
imports: [
ResolversModule,
GraphQLModule.forRootAsync<ApolloDriverConfig>({
driver: ApolloDriver,
useFactory: async () => ({
introspection: getters.config()?.local?.sandbox === 'yes',
playground: false,
context: ({ req, connectionParams, extra }: any) => ({
req,
connectionParams,
extra,
}),
plugins: [sandboxPlugin, idPrefixPlugin] as any[],
subscriptions: {
'graphql-ws': {
path: '/graphql',
imports: [PluginModule],
inject: [PluginService],
useFactory: async (pluginService: PluginService) => {
const plugins = await pluginService.getGraphQLConfiguration();
return {
introspection: getters.config()?.local?.sandbox === 'yes',
playground: false,
context: ({ req, connectionParams, extra }: any) => ({
req,
connectionParams,
extra,
}),
plugins: [sandboxPlugin, idPrefixPlugin] as any[],
subscriptions: {
'graphql-ws': {
path: '/graphql',
},
},
},
path: '/graphql',
typeDefs: print(await loadTypeDefs()),
resolvers: {
JSON: JSONResolver,
Long: GraphQLLong,
UUID: UUIDResolver,
DateTime: DateTimeResolver,
Port: PortResolver,
URL: URLResolver,
},
validationRules: [NoUnusedVariablesRule],
}),
path: '/graphql',
typeDefs: [print(await loadTypeDefs([plugins.typeDefs]))],
resolvers: {
JSON: JSONResolver,
Long: GraphQLLong,
UUID: UUIDResolver,
DateTime: DateTimeResolver,
Port: PortResolver,
URL: URLResolver,
...plugins.resolvers,
},
validationRules: [NoUnusedVariablesRule],
};
},
}),
],
providers: [

View File

@@ -0,0 +1,72 @@
import { Args, ResolveField, Resolver } from '@nestjs/graphql';
import { AuthActionVerb, AuthPossession, UsePermissions } from 'nest-authz';
import type { ArrayDiskInput, ArrayStateInput } from '@app/graphql/generated/api/types.js';
import { Resource } from '@app/graphql/generated/api/types.js';
import { ArrayService } from '@app/unraid-api/graph/resolvers/array/array.service.js';
@Resolver('ArrayMutations')
export class ArrayMutationsResolver {
constructor(private readonly arrayService: ArrayService) {}
@ResolveField('setState')
@UsePermissions({
action: AuthActionVerb.UPDATE,
resource: Resource.ARRAY,
possession: AuthPossession.ANY,
})
public async setState(@Args('input') input: ArrayStateInput) {
return this.arrayService.updateArrayState(input);
}
@ResolveField('addDiskToArray')
@UsePermissions({
action: AuthActionVerb.UPDATE,
resource: Resource.ARRAY,
possession: AuthPossession.ANY,
})
public async addDiskToArray(@Args('input') input: ArrayDiskInput) {
return this.arrayService.addDiskToArray(input);
}
@ResolveField('removeDiskFromArray')
@UsePermissions({
action: AuthActionVerb.UPDATE,
resource: Resource.ARRAY,
possession: AuthPossession.ANY,
})
public async removeDiskFromArray(@Args('input') input: ArrayDiskInput) {
return this.arrayService.removeDiskFromArray(input);
}
@ResolveField('mountArrayDisk')
@UsePermissions({
action: AuthActionVerb.UPDATE,
resource: Resource.ARRAY,
possession: AuthPossession.ANY,
})
public async mountArrayDisk(@Args('id') id: string) {
return this.arrayService.mountArrayDisk(id);
}
@ResolveField('unmountArrayDisk')
@UsePermissions({
action: AuthActionVerb.UPDATE,
resource: Resource.ARRAY,
possession: AuthPossession.ANY,
})
public async unmountArrayDisk(@Args('id') id: string) {
return this.arrayService.unmountArrayDisk(id);
}
@ResolveField('clearArrayDiskStatistics')
@UsePermissions({
action: AuthActionVerb.UPDATE,
resource: Resource.ARRAY,
possession: AuthPossession.ANY,
})
public async clearArrayDiskStatistics(@Args('id') id: string) {
return this.arrayService.clearArrayDiskStatistics(id);
}
}

View File

@@ -1,19 +1,35 @@
import type { TestingModule } from '@nestjs/testing';
import { Test } from '@nestjs/testing';
import { beforeEach, describe, expect, it } from 'vitest';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import { ArrayResolver } from '@app/unraid-api/graph/resolvers/array/array.resolver.js';
import { ArrayService } from '@app/unraid-api/graph/resolvers/array/array.service.js';
describe('ArrayResolver', () => {
let resolver: ArrayResolver;
let arrayService: ArrayService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [ArrayResolver],
providers: [
ArrayResolver,
{
provide: ArrayService,
useValue: {
updateArrayState: vi.fn(),
addDiskToArray: vi.fn(),
removeDiskFromArray: vi.fn(),
mountArrayDisk: vi.fn(),
unmountArrayDisk: vi.fn(),
clearArrayDiskStatistics: vi.fn(),
},
},
],
}).compile();
resolver = module.get<ArrayResolver>(ArrayResolver);
arrayService = module.get<ArrayService>(ArrayService);
});
it('should be defined', () => {

View File

@@ -6,9 +6,12 @@ import { getArrayData } from '@app/core/modules/array/get-array-data.js';
import { createSubscription, PUBSUB_CHANNEL } from '@app/core/pubsub.js';
import { Resource } from '@app/graphql/generated/api/types.js';
import { store } from '@app/store/index.js';
import { ArrayService } from '@app/unraid-api/graph/resolvers/array/array.service.js';
@Resolver('Array')
export class ArrayResolver {
constructor(private readonly arrayService: ArrayService) {}
@Query()
@UsePermissions({
action: AuthActionVerb.READ,

View File

@@ -0,0 +1,210 @@
import type { TestingModule } from '@nestjs/testing';
import { Test } from '@nestjs/testing';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import type { ArrayDiskInput, ArrayStateInput } from '@app/graphql/generated/api/types.js';
import { getArrayData } from '@app/core/modules/array/get-array-data.js';
import { emcmd } from '@app/core/utils/clients/emcmd.js';
import { ArrayState, ArrayStateInputState } from '@app/graphql/generated/api/types.js';
import { getters } from '@app/store/index.js';
import { ArrayService } from '@app/unraid-api/graph/resolvers/array/array.service.js';
vi.mock('@app/core/utils/clients/emcmd.js', () => ({
emcmd: vi.fn(),
}));
vi.mock('@app/store/index.js', () => ({
getters: {
emhttp: vi.fn(),
},
}));
vi.mock('@app/core/modules/array/get-array-data.js', () => ({
getArrayData: vi.fn(),
}));
describe('ArrayService', () => {
let service: ArrayService;
let mockArrayData: any;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [ArrayService],
}).compile();
service = module.get<ArrayService>(ArrayService);
// Mock getters.emhttp()
vi.mocked(getters.emhttp).mockReturnValue({
var: {
mdState: ArrayState.STOPPED,
},
} as any);
// Mock getArrayData
mockArrayData = {
id: 'array',
state: ArrayState.STOPPED,
capacity: {
kilobytes: {
free: '1000',
used: '1000',
total: '2000',
},
disks: {
free: '10',
used: '5',
total: '15',
},
},
boot: null,
parities: [],
disks: [],
caches: [],
};
vi.mocked(getArrayData).mockReturnValue(mockArrayData);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
it('should update array state', async () => {
const input: ArrayStateInput = {
desiredState: ArrayStateInputState.START,
};
const result = await service.updateArrayState(input);
expect(result).toEqual(mockArrayData);
expect(emcmd).toHaveBeenCalledWith({
cmdStart: 'Start',
startState: 'STOPPED',
});
});
it('should add disk to array', async () => {
const input: ArrayDiskInput = {
id: 'test-disk',
slot: 1,
};
const result = await service.addDiskToArray(input);
expect(result).toEqual(mockArrayData);
expect(emcmd).toHaveBeenCalledWith({
changeDevice: 'apply',
'slotId.1': 'test-disk',
});
});
it('should remove disk from array', async () => {
const input: ArrayDiskInput = {
id: 'test-disk',
slot: 1,
};
const result = await service.removeDiskFromArray(input);
expect(result).toEqual(mockArrayData);
expect(emcmd).toHaveBeenCalledWith({
changeDevice: 'apply',
'slotId.1': '',
});
});
it('should mount array disk', async () => {
// Mock array as running
vi.mocked(getters.emhttp).mockReturnValue({
var: {
mdState: ArrayState.STARTED,
},
} as any);
const result = await service.mountArrayDisk('test-disk');
expect(result).toEqual(mockArrayData);
expect(emcmd).toHaveBeenCalledWith({
mount: 'apply',
'diskId.test-disk': '1',
});
});
it('should unmount array disk', async () => {
// Mock array as running
vi.mocked(getters.emhttp).mockReturnValue({
var: {
mdState: ArrayState.STARTED,
},
} as any);
const result = await service.unmountArrayDisk('test-disk');
expect(result).toEqual(mockArrayData);
expect(emcmd).toHaveBeenCalledWith({
unmount: 'apply',
'diskId.test-disk': '1',
});
});
it('should clear array disk statistics', async () => {
// Mock array as running
vi.mocked(getters.emhttp).mockReturnValue({
var: {
mdState: ArrayState.STARTED,
},
} as any);
const result = await service.clearArrayDiskStatistics('test-disk');
expect(result).toEqual(mockArrayData);
expect(emcmd).toHaveBeenCalledWith({
clearStats: 'apply',
'diskId.test-disk': '1',
});
});
it('should throw error when array is running for add disk', async () => {
// Mock array as running
vi.mocked(getters.emhttp).mockReturnValue({
var: {
mdState: ArrayState.STARTED,
},
} as any);
const input: ArrayDiskInput = {
id: 'test-disk',
slot: 1,
};
await expect(service.addDiskToArray(input)).rejects.toThrow(
'Array needs to be stopped before any changes can occur.'
);
});
it('should throw error when array is running for remove disk', async () => {
// Mock array as running
vi.mocked(getters.emhttp).mockReturnValue({
var: {
mdState: ArrayState.STARTED,
},
} as any);
const input: ArrayDiskInput = {
id: 'test-disk',
slot: 1,
};
await expect(service.removeDiskFromArray(input)).rejects.toThrow(
'Array needs to be stopped before any changes can occur.'
);
});
it('should throw error when array is not running for mount disk', async () => {
await expect(service.mountArrayDisk('test-disk')).rejects.toThrow(
'Array must be running to mount disks'
);
});
it('should throw error when array is not running for unmount disk', async () => {
await expect(service.unmountArrayDisk('test-disk')).rejects.toThrow(
'Array must be running to unmount disks'
);
});
it('should throw error when array is not running for clear disk statistics', async () => {
await expect(service.clearArrayDiskStatistics('test-disk')).rejects.toThrow(
'Array must be running to clear disk statistics'
);
});
});

View File

@@ -0,0 +1,145 @@
import { BadRequestException, Injectable } from '@nestjs/common';
import { capitalCase, constantCase } from 'change-case';
import type { ArrayDiskInput, ArrayStateInput, ArrayType } from '@app/graphql/generated/api/types.js';
import { AppError } from '@app/core/errors/app-error.js';
import { ArrayRunningError } from '@app/core/errors/array-running-error.js';
import { getArrayData } from '@app/core/modules/array/get-array-data.js';
import { emcmd } from '@app/core/utils/clients/emcmd.js';
import { arrayIsRunning as arrayIsRunningUtil } from '@app/core/utils/index.js';
import {
ArrayPendingState,
ArrayState,
ArrayStateInputState,
} from '@app/graphql/generated/api/types.js';
@Injectable()
export class ArrayService {
private pendingState: ArrayPendingState | null = null;
/**
* Is the array running?
* @todo Refactor this to include this util in the service directly
*/
private arrayIsRunning() {
return arrayIsRunningUtil();
}
async updateArrayState({ desiredState }: ArrayStateInput): Promise<ArrayType> {
const startState = this.arrayIsRunning() ? ArrayState.STARTED : ArrayState.STOPPED;
const pendingState =
desiredState === ArrayStateInputState.STOP
? ArrayPendingState.STOPPING
: ArrayPendingState.STARTING;
// Prevent this running multiple times at once
if (this.pendingState) {
throw new BadRequestException(
new AppError(`Array state is still being updated. Changing to ${pendingState}`)
);
}
// Prevent starting/stopping array when it's already in the same state
if (
(this.arrayIsRunning() && desiredState === ArrayStateInputState.START) ||
(!this.arrayIsRunning() && desiredState === ArrayStateInputState.STOP)
) {
throw new BadRequestException(new AppError(`The array is already ${startState}`));
}
// Set lock then start/stop array
this.pendingState = pendingState;
const command = {
[`cmd${capitalCase(desiredState)}`]: capitalCase(desiredState),
startState: constantCase(startState),
};
try {
await emcmd(command);
} finally {
this.pendingState = null;
}
// Get new array JSON
const array = getArrayData();
return array;
}
async addDiskToArray(input: ArrayDiskInput): Promise<ArrayType> {
if (this.arrayIsRunning()) {
throw new ArrayRunningError();
}
const { id: diskId, slot: preferredSlot } = input;
const slot = preferredSlot?.toString() ?? '';
// Add disk
await emcmd({
changeDevice: 'apply',
[`slotId.${slot}`]: diskId,
});
return getArrayData();
}
async removeDiskFromArray(input: ArrayDiskInput): Promise<ArrayType> {
if (this.arrayIsRunning()) {
throw new ArrayRunningError();
}
const { slot } = input;
const slotStr = slot?.toString() ?? '';
// Remove disk
await emcmd({
changeDevice: 'apply',
[`slotId.${slotStr}`]: '',
});
return getArrayData();
}
async mountArrayDisk(id: string): Promise<ArrayType> {
if (!this.arrayIsRunning()) {
throw new BadRequestException('Array must be running to mount disks');
}
// Mount disk
await emcmd({
mount: 'apply',
[`diskId.${id}`]: '1',
});
return getArrayData();
}
async unmountArrayDisk(id: string): Promise<ArrayType> {
if (!this.arrayIsRunning()) {
throw new BadRequestException('Array must be running to unmount disks');
}
// Unmount disk
await emcmd({
unmount: 'apply',
[`diskId.${id}`]: '1',
});
return getArrayData();
}
async clearArrayDiskStatistics(id: string): Promise<ArrayType> {
if (!this.arrayIsRunning()) {
throw new BadRequestException('Array must be running to clear disk statistics');
}
// Clear disk statistics
await emcmd({
clearStats: 'apply',
[`diskId.${id}`]: '1',
});
return getArrayData();
}
}

View File

@@ -21,9 +21,7 @@ export class ConfigResolver {
return {
id: 'config',
valid: emhttp.var.configValid,
error: emhttp.var.configValid
? null
: (ConfigErrorState[emhttp.var.configState] ?? ConfigErrorState.UNKNOWN_ERROR),
error: emhttp.var.configValid ? null : emhttp.var.configErrorState,
};
}

View File

@@ -0,0 +1,74 @@
import type { TestingModule } from '@nestjs/testing';
import { Test } from '@nestjs/testing';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import type { DockerContainer } from '@app/graphql/generated/api/types.js';
import { ContainerState } from '@app/graphql/generated/api/types.js';
import { DockerMutationsResolver } from '@app/unraid-api/graph/resolvers/docker/docker.mutations.resolver.js';
import { DockerService } from '@app/unraid-api/graph/resolvers/docker/docker.service.js';
describe('DockerMutationsResolver', () => {
let resolver: DockerMutationsResolver;
let dockerService: DockerService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [
DockerMutationsResolver,
{
provide: DockerService,
useValue: {
startContainer: vi.fn(),
stopContainer: vi.fn(),
},
},
],
}).compile();
resolver = module.get<DockerMutationsResolver>(DockerMutationsResolver);
dockerService = module.get<DockerService>(DockerService);
});
it('should be defined', () => {
expect(resolver).toBeDefined();
});
it('should start container', async () => {
const mockContainer: DockerContainer = {
id: '1',
autoStart: false,
command: 'test',
created: 1234567890,
image: 'test-image',
imageId: 'test-image-id',
ports: [],
state: ContainerState.RUNNING,
status: 'Up 2 hours',
};
vi.mocked(dockerService.startContainer).mockResolvedValue(mockContainer);
const result = await resolver.startContainer('1');
expect(result).toEqual(mockContainer);
expect(dockerService.startContainer).toHaveBeenCalledWith('1');
});
it('should stop container', async () => {
const mockContainer: DockerContainer = {
id: '1',
autoStart: false,
command: 'test',
created: 1234567890,
image: 'test-image',
imageId: 'test-image-id',
ports: [],
state: ContainerState.EXITED,
status: 'Exited',
};
vi.mocked(dockerService.stopContainer).mockResolvedValue(mockContainer);
const result = await resolver.stopContainer('1');
expect(result).toEqual(mockContainer);
expect(dockerService.stopContainer).toHaveBeenCalledWith('1');
});
});

View File

@@ -0,0 +1,31 @@
import { Args, ResolveField, Resolver } from '@nestjs/graphql';
import { AuthActionVerb, AuthPossession, UsePermissions } from 'nest-authz';
import { Resource } from '@app/graphql/generated/api/types.js';
import { DockerService } from '@app/unraid-api/graph/resolvers/docker/docker.service.js';
@Resolver('DockerMutations')
export class DockerMutationsResolver {
constructor(private readonly dockerService: DockerService) {}
@ResolveField('startContainer')
@UsePermissions({
action: AuthActionVerb.UPDATE,
resource: Resource.DOCKER,
possession: AuthPossession.ANY,
})
public async startContainer(@Args('id') id: string) {
return this.dockerService.startContainer(id);
}
@ResolveField('stopContainer')
@UsePermissions({
action: AuthActionVerb.UPDATE,
resource: Resource.DOCKER,
possession: AuthPossession.ANY,
})
public async stopContainer(@Args('id') id: string) {
return this.dockerService.stopContainer(id);
}
}

View File

@@ -1,22 +1,77 @@
import type { TestingModule } from '@nestjs/testing';
import { Test } from '@nestjs/testing';
import { beforeEach, describe, expect, it } from 'vitest';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import type { DockerContainer } from '@app/graphql/generated/api/types.js';
import { ContainerState } from '@app/graphql/generated/api/types.js';
import { DockerResolver } from '@app/unraid-api/graph/resolvers/docker/docker.resolver.js';
import { DockerService } from '@app/unraid-api/graph/resolvers/docker/docker.service.js';
describe('DockerResolver', () => {
let resolver: DockerResolver;
let dockerService: DockerService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [DockerResolver],
providers: [
DockerResolver,
{
provide: DockerService,
useValue: {
getContainers: vi.fn(),
},
},
],
}).compile();
resolver = module.get<DockerResolver>(DockerResolver);
dockerService = module.get<DockerService>(DockerService);
});
it('should be defined', () => {
expect(resolver).toBeDefined();
});
it('should return docker object with id', () => {
const result = resolver.docker();
expect(result).toEqual({ id: 'docker' });
});
it('should return containers from service', async () => {
const mockContainers: DockerContainer[] = [
{
id: '1',
autoStart: false,
command: 'test',
created: 1234567890,
image: 'test-image',
imageId: 'test-image-id',
ports: [],
state: ContainerState.EXITED,
status: 'Exited',
},
{
id: '2',
autoStart: true,
command: 'test2',
created: 1234567891,
image: 'test-image2',
imageId: 'test-image-id2',
ports: [],
state: ContainerState.RUNNING,
status: 'Up 2 hours',
},
];
vi.mocked(dockerService.getContainers).mockResolvedValue(mockContainers);
const result = await resolver.containers();
expect(result).toEqual(mockContainers);
expect(dockerService.getContainers).toHaveBeenCalledWith({ useCache: false });
});
it('should return mutations object with id', () => {
const result = resolver.mutations();
expect(result).toEqual({ id: 'docker-mutations' });
});
});

View File

@@ -3,9 +3,12 @@ import { Query, ResolveField, Resolver } from '@nestjs/graphql';
import { AuthActionVerb, AuthPossession, UsePermissions } from 'nest-authz';
import { Resource } from '@app/graphql/generated/api/types.js';
import { DockerService } from '@app/unraid-api/graph/resolvers/docker/docker.service.js';
@Resolver('Docker')
export class DockerResolver {
constructor(private readonly dockerService: DockerService) {}
@UsePermissions({
action: AuthActionVerb.READ,
resource: Resource.DOCKER,
@@ -25,10 +28,13 @@ export class DockerResolver {
})
@ResolveField()
public async containers() {
const { getDockerContainers } = await import(
'@app/core/modules/docker/get-docker-containers.js'
);
return this.dockerService.getContainers({ useCache: false });
}
return getDockerContainers({ useCache: false });
@ResolveField()
public mutations() {
return {
id: 'docker-mutations',
};
}
}

View File

@@ -0,0 +1,125 @@
import type { TestingModule } from '@nestjs/testing';
import { Test } from '@nestjs/testing';
import { beforeEach, describe, expect, it, vi } from 'vitest';
import type { DockerContainer } from '@app/graphql/generated/api/types.js';
import { getDockerContainers } from '@app/core/modules/docker/get-docker-containers.js';
import { docker } from '@app/core/utils/clients/docker.js';
import { ContainerState } from '@app/graphql/generated/api/types.js';
import { DockerService } from '@app/unraid-api/graph/resolvers/docker/docker.service.js';
vi.mock('@app/core/utils/clients/docker.js', () => ({
docker: {
getContainer: vi.fn(),
listContainers: vi.fn(),
},
}));
vi.mock('@app/core/modules/docker/get-docker-containers.js', () => ({
getDockerContainers: vi.fn(),
}));
describe('DockerService', () => {
let service: DockerService;
let mockContainer: any;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [DockerService],
}).compile();
service = module.get<DockerService>(DockerService);
mockContainer = {
start: vi.fn(),
stop: vi.fn(),
};
vi.mocked(docker.getContainer).mockReturnValue(mockContainer as any);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
it('should get containers', async () => {
const mockContainers: DockerContainer[] = [
{
id: '1',
autoStart: false,
command: 'test',
created: 1234567890,
image: 'test-image',
imageId: 'test-image-id',
ports: [],
state: ContainerState.EXITED,
status: 'Exited',
},
];
vi.mocked(getDockerContainers).mockResolvedValue(mockContainers);
const result = await service.getContainers({ useCache: false });
expect(result).toEqual(mockContainers);
expect(getDockerContainers).toHaveBeenCalledWith({ useCache: false });
});
it('should start container', async () => {
const mockContainers: DockerContainer[] = [
{
id: '1',
autoStart: false,
command: 'test',
created: 1234567890,
image: 'test-image',
imageId: 'test-image-id',
ports: [],
state: ContainerState.RUNNING,
status: 'Up 2 hours',
},
];
vi.mocked(getDockerContainers).mockResolvedValue(mockContainers);
const result = await service.startContainer('1');
expect(result).toEqual(mockContainers[0]);
expect(docker.getContainer).toHaveBeenCalledWith('1');
expect(mockContainer.start).toHaveBeenCalled();
expect(getDockerContainers).toHaveBeenCalledWith({ useCache: false });
});
it('should stop container', async () => {
const mockContainers: DockerContainer[] = [
{
id: '1',
autoStart: false,
command: 'test',
created: 1234567890,
image: 'test-image',
imageId: 'test-image-id',
ports: [],
state: ContainerState.EXITED,
status: 'Exited',
},
];
vi.mocked(getDockerContainers).mockResolvedValue(mockContainers);
const result = await service.stopContainer('1');
expect(result).toEqual(mockContainers[0]);
expect(docker.getContainer).toHaveBeenCalledWith('1');
expect(mockContainer.stop).toHaveBeenCalled();
expect(getDockerContainers).toHaveBeenCalledWith({ useCache: false });
});
it('should throw error if container not found after start', async () => {
vi.mocked(getDockerContainers).mockResolvedValue([]);
await expect(service.startContainer('1')).rejects.toThrow(
'Container 1 not found after starting'
);
});
it('should throw error if container not found after stop', async () => {
vi.mocked(getDockerContainers).mockResolvedValue([]);
await expect(service.stopContainer('1')).rejects.toThrow('Container 1 not found after stopping');
});
});

View File

@@ -0,0 +1,37 @@
import { Injectable } from '@nestjs/common';
import type { DockerContainer } from '@app/graphql/generated/api/types.js';
import {
ContainerListingOptions,
getDockerContainers,
} from '@app/core/modules/docker/get-docker-containers.js';
import { docker } from '@app/core/utils/clients/docker.js';
@Injectable()
export class DockerService {
public async getContainers({ useCache }: ContainerListingOptions): Promise<DockerContainer[]> {
return getDockerContainers({ useCache });
}
public async startContainer(id: string): Promise<DockerContainer> {
const container = docker.getContainer(id);
await container.start();
const containers = await this.getContainers({ useCache: false });
const updatedContainer = containers.find((c) => c.id === id);
if (!updatedContainer) {
throw new Error(`Container ${id} not found after starting`);
}
return updatedContainer;
}
public async stopContainer(id: string): Promise<DockerContainer> {
const container = docker.getContainer(id);
await container.stop();
const containers = await this.getContainers({ useCache: false });
const updatedContainer = containers.find((c) => c.id === id);
if (!updatedContainer) {
throw new Error(`Container ${id} not found after stopping`);
}
return updatedContainer;
}
}

View File

@@ -0,0 +1,11 @@
import { ResolveField, Resolver } from '@nestjs/graphql';
@Resolver('Mutation')
export class MutationResolver {
@ResolveField()
public async array() {
return {
__typename: 'ArrayMutations',
};
}
}

View File

@@ -3,17 +3,22 @@ import { Module } from '@nestjs/common';
import { AuthModule } from '@app/unraid-api/auth/auth.module.js';
import { ConnectSettingsService } from '@app/unraid-api/graph/connect/connect-settings.service.js';
import { ApiKeyResolver } from '@app/unraid-api/graph/resolvers/api-key/api-key.resolver.js';
import { ArrayMutationsResolver } from '@app/unraid-api/graph/resolvers/array/array.mutations.resolver.js';
import { ArrayResolver } from '@app/unraid-api/graph/resolvers/array/array.resolver.js';
import { ArrayService } from '@app/unraid-api/graph/resolvers/array/array.service.js';
import { CloudResolver } from '@app/unraid-api/graph/resolvers/cloud/cloud.resolver.js';
import { ConfigResolver } from '@app/unraid-api/graph/resolvers/config/config.resolver.js';
import { DisksResolver } from '@app/unraid-api/graph/resolvers/disks/disks.resolver.js';
import { DisplayResolver } from '@app/unraid-api/graph/resolvers/display/display.resolver.js';
import { DockerMutationsResolver } from '@app/unraid-api/graph/resolvers/docker/docker.mutations.resolver.js';
import { DockerResolver } from '@app/unraid-api/graph/resolvers/docker/docker.resolver.js';
import { DockerService } from '@app/unraid-api/graph/resolvers/docker/docker.service.js';
import { FlashResolver } from '@app/unraid-api/graph/resolvers/flash/flash.resolver.js';
import { InfoResolver } from '@app/unraid-api/graph/resolvers/info/info.resolver.js';
import { LogsResolver } from '@app/unraid-api/graph/resolvers/logs/logs.resolver.js';
import { LogsService } from '@app/unraid-api/graph/resolvers/logs/logs.service.js';
import { MeResolver } from '@app/unraid-api/graph/resolvers/me/me.resolver.js';
import { MutationResolver } from '@app/unraid-api/graph/resolvers/mutation/mutation.resolver.js';
import { NotificationsResolver } from '@app/unraid-api/graph/resolvers/notifications/notifications.resolver.js';
import { NotificationsService } from '@app/unraid-api/graph/resolvers/notifications/notifications.service.js';
import { OnlineResolver } from '@app/unraid-api/graph/resolvers/online/online.resolver.js';
@@ -27,13 +32,18 @@ import { VmsResolver } from '@app/unraid-api/graph/resolvers/vms/vms.resolver.js
imports: [AuthModule],
providers: [
ArrayResolver,
ArrayMutationsResolver,
ArrayService,
ApiKeyResolver,
CloudResolver,
ConfigResolver,
DisksResolver,
DisplayResolver,
DockerResolver,
DockerMutationsResolver,
DockerService,
FlashResolver,
MutationResolver,
InfoResolver,
NotificationsResolver,
OnlineResolver,

Some files were not shown because too many files have changed in this diff Show More