diff --git a/.vscode/settings.json b/.vscode/settings.json
index 4bf115e25..94ed7a3fc 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -4,24 +4,15 @@
"mode": "auto"
}
],
+ "eslint.experimental.useFlatConfig": true,
"typescript.tsdk": "node_modules\\typescript\\lib",
"js/ts.implicitProjectConfig.experimentalDecorators": true,
"prettier.configPath": "./tooling/prettier/index.mjs",
- "cSpell.words": [
- "cqmin",
- "homarr",
- "superjson",
- "trpc",
- "Umami"
- ],
+ "cSpell.words": ["cqmin", "homarr", "superjson", "trpc", "Umami"],
"i18n-ally.dirStructure": "auto",
- "i18n-ally.enabledFrameworks": [
- "next-international"
- ],
- "i18n-ally.localesPaths": [
- "./packages/translation/src/lang/",
- ],
+ "i18n-ally.enabledFrameworks": ["next-international"],
+ "i18n-ally.localesPaths": ["./packages/translation/src/lang/"],
"i18n-ally.enabledParsers": ["ts"],
"i18n-ally.extract.keyMaxLength": 0,
- "i18n-ally.keystyle": "flat",
-}
\ No newline at end of file
+ "i18n-ally.keystyle": "flat"
+}
diff --git a/apps/nextjs/eslint.config.js b/apps/nextjs/eslint.config.js
new file mode 100644
index 000000000..c131bab90
--- /dev/null
+++ b/apps/nextjs/eslint.config.js
@@ -0,0 +1,13 @@
+import baseConfig from "@homarr/eslint-config/base";
+import nextjsConfig from "@homarr/eslint-config/nextjs";
+import reactConfig from "@homarr/eslint-config/react";
+
+/** @type {import('typescript-eslint').Config} */
+export default [
+ {
+ ignores: [".next/**"],
+ },
+ ...baseConfig,
+ ...reactConfig,
+ ...nextjsConfig,
+];
diff --git a/apps/nextjs/next.config.mjs b/apps/nextjs/next.config.mjs
index 970d393c4..0cc05f786 100644
--- a/apps/nextjs/next.config.mjs
+++ b/apps/nextjs/next.config.mjs
@@ -10,12 +10,10 @@ const config = {
eslint: { ignoreDuringBuilds: true },
typescript: { ignoreBuildErrors: true },
webpack: (config) => {
- // eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
config.module.rules.push({
test: /\.node$/,
loader: "node-loader",
});
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
return config;
},
experimental: {
diff --git a/apps/nextjs/package.json b/apps/nextjs/package.json
index a19b9f728..0fdf8888c 100644
--- a/apps/nextjs/package.json
+++ b/apps/nextjs/package.json
@@ -7,7 +7,7 @@
"build": "pnpm with-env next build",
"clean": "git clean -xdf .next .turbo node_modules",
"dev": "pnpm with-env next dev",
- "lint": "dotenv -v SKIP_ENV_VALIDATION=1 next lint",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"start": "pnpm with-env next start",
"typecheck": "tsc --noEmit",
@@ -73,19 +73,11 @@
"@types/react": "^18.3.3",
"@types/react-dom": "^18.3.0",
"concurrently": "^8.2.2",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"node-loader": "^2.0.0",
"prettier": "^3.3.1",
"tsx": "4.14.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "root": true,
- "extends": [
- "@homarr/eslint-config/base",
- "@homarr/eslint-config/nextjs",
- "@homarr/eslint-config/react"
- ]
- },
"prettier": "@homarr/prettier-config"
}
diff --git a/apps/nextjs/src/app/[locale]/boards/(content)/_context.tsx b/apps/nextjs/src/app/[locale]/boards/(content)/_context.tsx
index 808759af1..346baff75 100644
--- a/apps/nextjs/src/app/[locale]/boards/(content)/_context.tsx
+++ b/apps/nextjs/src/app/[locale]/boards/(content)/_context.tsx
@@ -49,7 +49,6 @@ export const BoardProvider = ({
useEffect(() => {
setReadySections((previous) => previous.filter((id) => data.sections.some((section) => section.id === id)));
- // eslint-disable-next-line react-hooks/exhaustive-deps
}, [data.sections.length, setReadySections]);
const markAsReady = useCallback((id: string) => {
diff --git a/apps/nextjs/src/app/[locale]/boards/(content)/_theme.tsx b/apps/nextjs/src/app/[locale]/boards/(content)/_theme.tsx
index bf68bb902..e3c87aa05 100644
--- a/apps/nextjs/src/app/[locale]/boards/(content)/_theme.tsx
+++ b/apps/nextjs/src/app/[locale]/boards/(content)/_theme.tsx
@@ -33,6 +33,7 @@ export const generateColors = (hex: string) => {
return rgbaColors.map((color) => {
return (
"#" +
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
color
.split("(")[1]!
.replaceAll(" ", "")
diff --git a/apps/nextjs/src/app/[locale]/boards/[name]/settings/_access/group-access.tsx b/apps/nextjs/src/app/[locale]/boards/[name]/settings/_access/group-access.tsx
index f465b6c08..7a6c4dce3 100644
--- a/apps/nextjs/src/app/[locale]/boards/[name]/settings/_access/group-access.tsx
+++ b/apps/nextjs/src/app/[locale]/boards/[name]/settings/_access/group-access.tsx
@@ -81,6 +81,7 @@ export const GroupsForm = ({ board, initialPermissions, onCountChange }: FormPro
{form.values.items.map((row, index) => (
}
permission={row.permission}
index={index}
diff --git a/apps/nextjs/src/app/[locale]/boards/[name]/settings/_access/user-access.tsx b/apps/nextjs/src/app/[locale]/boards/[name]/settings/_access/user-access.tsx
index 8ed7e98ee..775925252 100644
--- a/apps/nextjs/src/app/[locale]/boards/[name]/settings/_access/user-access.tsx
+++ b/apps/nextjs/src/app/[locale]/boards/[name]/settings/_access/user-access.tsx
@@ -93,6 +93,7 @@ export const UsersForm = ({ board, initialPermissions, onCountChange }: FormProp
{form.values.items.map((row, index) => (
}
permission={row.permission}
index={index}
diff --git a/apps/nextjs/src/app/[locale]/compose.tsx b/apps/nextjs/src/app/[locale]/compose.tsx
index 6997ca986..e7899c938 100644
--- a/apps/nextjs/src/app/[locale]/compose.tsx
+++ b/apps/nextjs/src/app/[locale]/compose.tsx
@@ -6,7 +6,6 @@ export const composeWrappers = (
wrappers: React.FunctionComponent[],
): React.FunctionComponent => {
return wrappers.reverse().reduce((Acc, Current): React.FunctionComponent => {
- // eslint-disable-next-line react/display-name
return (props) => (
diff --git a/apps/nextjs/src/app/[locale]/manage/about/page.tsx b/apps/nextjs/src/app/[locale]/manage/about/page.tsx
index a1dadf037..a29e44e0f 100644
--- a/apps/nextjs/src/app/[locale]/manage/about/page.tsx
+++ b/apps/nextjs/src/app/[locale]/manage/about/page.tsx
@@ -21,11 +21,11 @@ import { setStaticParamsLocale } from "next-international/server";
import { getScopedI18n, getStaticParams } from "@homarr/translation/server";
+import { homarrLogoPath } from "~/components/layout/logo/homarr-logo";
import { createMetaTitle } from "~/metadata";
import { getPackageAttributesAsync } from "~/versions/package-reader";
import contributorsData from "../../../../../../../static-data/contributors.json";
import translatorsData from "../../../../../../../static-data/translators.json";
-import logo from "../../../../../public/logo/logo.png";
import classes from "./about.module.css";
export async function generateMetadata() {
@@ -50,7 +50,7 @@ export default async function AboutPage({ params: { locale } }: PageProps) {
-
+
Homarr
diff --git a/apps/nextjs/src/app/[locale]/manage/boards/page.tsx b/apps/nextjs/src/app/[locale]/manage/boards/page.tsx
index 5dc4c79d7..906262eb4 100644
--- a/apps/nextjs/src/app/[locale]/manage/boards/page.tsx
+++ b/apps/nextjs/src/app/[locale]/manage/boards/page.tsx
@@ -83,7 +83,7 @@ const BoardCard = async ({ board }: BoardCardProps) => {
{board.creator && (
- {board.creator?.name}
+ {board.creator.name}
)}
diff --git a/apps/nextjs/src/app/[locale]/manage/integrations/edit/[id]/_integration-edit-form.tsx b/apps/nextjs/src/app/[locale]/manage/integrations/edit/[id]/_integration-edit-form.tsx
index e1521abd2..c93826e92 100644
--- a/apps/nextjs/src/app/[locale]/manage/integrations/edit/[id]/_integration-edit-form.tsx
+++ b/apps/nextjs/src/app/[locale]/manage/integrations/edit/[id]/_integration-edit-form.tsx
@@ -95,6 +95,7 @@ export const EditIntegrationForm = ({ integration }: EditIntegrationForm) => {
{secretsKinds.map((kind, index) => (
new Promise((res) => {
@@ -107,7 +108,7 @@ export const EditIntegrationForm = ({ integration }: EditIntegrationForm) => {
children: t("integration.secrets.reset.message"),
onCancel: () => res(false),
onConfirm: () => {
- form.setFieldValue(`secrets.${index}.value`, secretsMap.get(kind)!.value ?? "");
+ form.setFieldValue(`secrets.${index}.value`, secretsMap.get(kind)?.value ?? "");
res(true);
},
});
diff --git a/apps/nextjs/src/app/[locale]/manage/integrations/new/page.tsx b/apps/nextjs/src/app/[locale]/manage/integrations/new/page.tsx
index 23eb474f5..0db877a11 100644
--- a/apps/nextjs/src/app/[locale]/manage/integrations/new/page.tsx
+++ b/apps/nextjs/src/app/[locale]/manage/integrations/new/page.tsx
@@ -17,6 +17,7 @@ interface NewIntegrationPageProps {
}
export default async function IntegrationsNewPage({ searchParams }: NewIntegrationPageProps) {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const result = z.enum([integrationKinds[0]!, ...integrationKinds.slice(1)]).safeParse(searchParams.kind);
if (!result.success) {
notFound();
diff --git a/apps/nextjs/src/app/[locale]/manage/integrations/page.tsx b/apps/nextjs/src/app/[locale]/manage/integrations/page.tsx
index 07b4c894d..15ff2ef83 100644
--- a/apps/nextjs/src/app/[locale]/manage/integrations/page.tsx
+++ b/apps/nextjs/src/app/[locale]/manage/integrations/page.tsx
@@ -82,6 +82,7 @@ const IntegrationList = async ({ integrations, activeTab }: IntegrationListProps
const grouppedIntegrations = integrations.reduce(
(acc, integration) => {
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!acc[integration.kind]) {
acc[integration.kind] = [];
}
diff --git a/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/_components/_profile-avatar-form.tsx b/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/_components/_profile-avatar-form.tsx
index 0e819d163..4ad991bd6 100644
--- a/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/_components/_profile-avatar-form.tsx
+++ b/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/_components/_profile-avatar-form.tsx
@@ -136,6 +136,6 @@ const fileToBase64Async = async (file: File): Promise =>
new Promise((resolve, reject) => {
const reader = new FileReader();
reader.readAsDataURL(file);
- reader.onload = () => resolve(reader.result?.toString() || "");
+ reader.onload = () => resolve(reader.result?.toString() ?? "");
reader.onerror = reject;
});
diff --git a/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/page.tsx b/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/page.tsx
index 82d3a6f89..3dfcfca59 100644
--- a/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/page.tsx
+++ b/apps/nextjs/src/app/[locale]/manage/users/[userId]/general/page.tsx
@@ -35,7 +35,7 @@ export async function generateMetadata({ params }: Props) {
const t = await getScopedI18n("management.page.user.edit");
return {
- title: createMetaTitle(t("metaTitle", { username: user?.name })),
+ title: createMetaTitle(t("metaTitle", { username: user.name })),
};
}
diff --git a/apps/nextjs/src/app/[locale]/manage/users/create/_components/create-user-stepper.tsx b/apps/nextjs/src/app/[locale]/manage/users/create/_components/create-user-stepper.tsx
index eadf51ddd..7526e821a 100644
--- a/apps/nextjs/src/app/[locale]/manage/users/create/_components/create-user-stepper.tsx
+++ b/apps/nextjs/src/app/[locale]/manage/users/create/_components/create-user-stepper.tsx
@@ -71,7 +71,8 @@ export const UserCreateStepperComponent = () => {
const allForms = useMemo(() => [generalForm, securityForm], [generalForm, securityForm]);
- const isCurrentFormValid = allForms[active] ? (allForms[active]!.isValid satisfies () => boolean) : () => true;
+ const activeForm = allForms[active];
+ const isCurrentFormValid = activeForm ? activeForm.isValid : () => true;
const canNavigateToNextStep = isCurrentFormValid();
const controlledGoToNextStep = useCallback(async () => {
diff --git a/apps/nextjs/src/app/[locale]/manage/users/groups/[id]/members/page.tsx b/apps/nextjs/src/app/[locale]/manage/users/groups/[id]/members/page.tsx
index 7f694ba6b..e5f0fc604 100644
--- a/apps/nextjs/src/app/[locale]/manage/users/groups/[id]/members/page.tsx
+++ b/apps/nextjs/src/app/[locale]/manage/users/groups/[id]/members/page.tsx
@@ -24,7 +24,8 @@ export default async function GroupsDetailPage({ params, searchParams }: GroupsD
const group = await api.group.getById({ id: params.id });
const filteredMembers = searchParams.search
- ? group.members.filter((member) => member.name?.toLowerCase().includes(searchParams.search!.trim().toLowerCase()))
+ ? // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
+ group.members.filter((member) => member.name?.toLowerCase().includes(searchParams.search!.trim().toLowerCase()))
: group.members;
return (
diff --git a/apps/nextjs/src/components/board/items/item-actions.tsx b/apps/nextjs/src/components/board/items/item-actions.tsx
index 2246853ea..5fd6c0841 100644
--- a/apps/nextjs/src/components/board/items/item-actions.tsx
+++ b/apps/nextjs/src/components/board/items/item-actions.tsx
@@ -90,7 +90,6 @@ export const useItemActions = () => {
const updateItemOptions = useCallback(
({ itemId, newOptions }: UpdateItemOptions) => {
updateBoard((previous) => {
- if (!previous) return previous;
return {
...previous,
sections: previous.sections.map((section) => {
@@ -117,7 +116,6 @@ export const useItemActions = () => {
const updateItemAdvancedOptions = useCallback(
({ itemId, newAdvancedOptions }: UpdateItemAdvancedOptions) => {
updateBoard((previous) => {
- if (!previous) return previous;
return {
...previous,
sections: previous.sections.map((section) => {
@@ -144,7 +142,6 @@ export const useItemActions = () => {
const updateItemIntegrations = useCallback(
({ itemId, newIntegrations }: UpdateItemIntegrations) => {
updateBoard((previous) => {
- if (!previous) return previous;
return {
...previous,
sections: previous.sections.map((section) => {
diff --git a/apps/nextjs/src/components/board/sections/category/category-actions.ts b/apps/nextjs/src/components/board/sections/category/category-actions.ts
index f78144536..c29751f38 100644
--- a/apps/nextjs/src/components/board/sections/category/category-actions.ts
+++ b/apps/nextjs/src/components/board/sections/category/category-actions.ts
@@ -37,6 +37,7 @@ export const useCategoryActions = () => {
sections: [
// Place sections before the new category
...previous.sections.filter(
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
(section) => (section.kind === "category" || section.kind === "empty") && section.position < position,
),
{
@@ -56,6 +57,7 @@ export const useCategoryActions = () => {
...previous.sections
.filter(
(section): section is CategorySection | EmptySection =>
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
(section.kind === "category" || section.kind === "empty") && section.position >= position,
)
.map((section) => ({
@@ -74,6 +76,7 @@ export const useCategoryActions = () => {
const lastSection = previous.sections
.filter(
(section): section is CategorySection | EmptySection =>
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
section.kind === "empty" || section.kind === "category",
)
.sort((sectionA, sectionB) => sectionB.position - sectionA.position)
@@ -130,12 +133,13 @@ export const useCategoryActions = () => {
(section): section is CategorySection => section.kind === "category" && section.id === id,
);
if (!currentCategory) return previous;
- if (currentCategory?.position === 1 && direction === "up") return previous;
- if (currentCategory?.position === previous.sections.length - 2 && direction === "down") return previous;
+ if (currentCategory.position === 1 && direction === "up") return previous;
+ if (currentCategory.position === previous.sections.length - 2 && direction === "down") return previous;
return {
...previous,
sections: previous.sections.map((section) => {
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (section.kind !== "category" && section.kind !== "empty") return section;
const offset = direction === "up" ? -2 : 2;
// Move category and empty section
diff --git a/apps/nextjs/src/components/board/sections/content.tsx b/apps/nextjs/src/components/board/sections/content.tsx
index 10d26a236..96ceaed99 100644
--- a/apps/nextjs/src/components/board/sections/content.tsx
+++ b/apps/nextjs/src/components/board/sections/content.tsx
@@ -1,6 +1,3 @@
-/* eslint-disable react/no-unknown-property */
-// Ignored because of gridstack attributes
-
import type { RefObject } from "react";
import { useEffect, useMemo, useRef } from "react";
import { ActionIcon, Card, Menu } from "@mantine/core";
@@ -122,6 +119,7 @@ const BoardItemContent = ({ item, ...dimensions }: ItemContentProps) => {
{
const itemId = changedNode.el?.getAttribute("data-id");
- if (!itemId) return;
+ if (!itemId || !changedNode.x || !changedNode.y || !changedNode.w || !changedNode.h) return;
// Updates the react-query state
moveAndResizeItem({
itemId,
- xOffset: changedNode.x!,
- yOffset: changedNode.y!,
- width: changedNode.w!,
- height: changedNode.h!,
+ xOffset: changedNode.x,
+ yOffset: changedNode.y,
+ width: changedNode.w,
+ height: changedNode.h,
});
},
[moveAndResizeItem],
@@ -70,16 +70,16 @@ export const useGridstack = ({ section, mainRef }: UseGridstackProps): UseGrista
const onAdd = useCallback(
(addedNode: GridStackNode) => {
const itemId = addedNode.el?.getAttribute("data-id");
- if (!itemId) return;
+ if (!itemId || !addedNode.x || !addedNode.y || !addedNode.w || !addedNode.h) return;
// Updates the react-query state
moveItemToSection({
itemId,
sectionId: section.id,
- xOffset: addedNode.x!,
- yOffset: addedNode.y!,
- width: addedNode.w!,
- height: addedNode.h!,
+ xOffset: addedNode.x,
+ yOffset: addedNode.y,
+ width: addedNode.w,
+ height: addedNode.h,
});
},
[moveItemToSection, section.id],
@@ -121,7 +121,6 @@ export const useGridstack = ({ section, mainRef }: UseGridstackProps): UseGrista
}
// Only run this effect when the section items change
- // eslint-disable-next-line react-hooks/exhaustive-deps
}, [items.length, section.items.length, board.columnCount]);
return {
diff --git a/apps/nextjs/src/components/layout/background.tsx b/apps/nextjs/src/components/layout/background.tsx
index 1c5b7c8b4..5c991e1a6 100644
--- a/apps/nextjs/src/components/layout/background.tsx
+++ b/apps/nextjs/src/components/layout/background.tsx
@@ -20,11 +20,11 @@ export const useOptionalBackgroundProps = (): Partial => {
}
return {
- bg: `url(${board?.backgroundImageUrl})`,
+ bg: `url(${board.backgroundImageUrl})`,
bgp: "center center",
- bgsz: board?.backgroundImageSize ?? "cover",
- bgr: board?.backgroundImageRepeat ?? "no-repeat",
- bga: board?.backgroundImageAttachment ?? "fixed",
+ bgsz: board.backgroundImageSize,
+ bgr: board.backgroundImageRepeat,
+ bga: board.backgroundImageAttachment,
};
};
@@ -49,7 +49,7 @@ export const BoardBackgroundVideo = () => {
height: "100vh",
top: 0,
left: 0,
- objectFit: board.backgroundImageSize ?? "cover",
+ objectFit: board.backgroundImageSize,
}}
>
diff --git a/apps/nextjs/src/components/layout/header/button.tsx b/apps/nextjs/src/components/layout/header/button.tsx
index 0604c137b..98bdbe0b7 100644
--- a/apps/nextjs/src/components/layout/header/button.tsx
+++ b/apps/nextjs/src/components/layout/header/button.tsx
@@ -22,7 +22,6 @@ const headerButtonActionIconProps: ActionIconProps = {
size: "lg",
};
-// eslint-disable-next-line react/display-name
export const HeaderButton = forwardRef((props, ref) => {
if ("href" in props) {
return (
diff --git a/apps/nextjs/src/components/user-avatar-menu.tsx b/apps/nextjs/src/components/user-avatar-menu.tsx
index a9f47d9ab..0cd5e0726 100644
--- a/apps/nextjs/src/components/user-avatar-menu.tsx
+++ b/apps/nextjs/src/components/user-avatar-menu.tsx
@@ -72,7 +72,7 @@ export const UserAvatarMenu = ({ children }: UserAvatarMenuProps) => {
<>
}
>
{t("preferences")}
diff --git a/apps/nextjs/src/components/user-avatar.tsx b/apps/nextjs/src/components/user-avatar.tsx
index d75606caf..9ddfba554 100644
--- a/apps/nextjs/src/components/user-avatar.tsx
+++ b/apps/nextjs/src/components/user-avatar.tsx
@@ -17,7 +17,8 @@ export const UserAvatar = async ({ size }: UserAvatarProps) => {
if (!currentSession?.user) return ;
if (currentSession.user.image)
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return ;
- return {currentSession.user.name!.substring(0, 2).toUpperCase()};
+ return {currentSession.user.name?.substring(0, 2).toUpperCase()};
};
diff --git a/apps/tasks/eslint.config.js b/apps/tasks/eslint.config.js
new file mode 100644
index 000000000..eddd608e5
--- /dev/null
+++ b/apps/tasks/eslint.config.js
@@ -0,0 +1,9 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [
+ {
+ ignores: ["build/**"],
+ },
+ ...baseConfig,
+];
diff --git a/apps/tasks/package.json b/apps/tasks/package.json
index 2140f78cf..dbcff5525 100644
--- a/apps/tasks/package.json
+++ b/apps/tasks/package.json
@@ -13,7 +13,7 @@
"dev": "pnpm with-env tsx ./src/main.ts",
"build": "esbuild src/main.ts --bundle --platform=node --outfile=tasks.cjs",
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit",
"with-env": "dotenv -e ../../.env --"
@@ -40,16 +40,10 @@
"@types/node-cron": "^3.0.11",
"@types/node": "^20.14.2",
"dotenv-cli": "^7.4.2",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"prettier": "^3.3.1",
"tsx": "4.14.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "root": true,
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config"
}
diff --git a/apps/websocket/eslint.config.js b/apps/websocket/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/apps/websocket/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/apps/websocket/package.json b/apps/websocket/package.json
index 69cd4af39..8ae96995f 100644
--- a/apps/websocket/package.json
+++ b/apps/websocket/package.json
@@ -10,7 +10,7 @@
"dev": "pnpm with-env tsx ./src/main.ts",
"build": "esbuild src/main.ts --bundle --platform=node --outfile=wssServer.cjs --external:bcrypt --loader:.html=text --loader:.node=text",
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit",
"with-env": "dotenv -e ../../.env --"
@@ -32,15 +32,9 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/ws": "^8.5.10",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"prettier": "^3.3.1",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "root": true,
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config"
}
diff --git a/packages/analytics/eslint.config.js b/packages/analytics/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/packages/analytics/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/packages/analytics/package.json b/packages/analytics/package.json
index 7d2c49d17..a0f900c48 100644
--- a/packages/analytics/package.json
+++ b/packages/analytics/package.json
@@ -16,7 +16,7 @@
"license": "MIT",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -27,14 +27,9 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/server-settings": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config",
"dependencies": {
"@umami/node": "^0.3.0",
diff --git a/packages/api/eslint.config.js b/packages/api/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/packages/api/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/packages/api/package.json b/packages/api/package.json
index 5024055bd..e17d26c4f 100644
--- a/packages/api/package.json
+++ b/packages/api/package.json
@@ -14,7 +14,7 @@
"type": "module",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -40,15 +40,9 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/dockerode": "^3.3.29",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"prettier": "^3.3.1",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "root": true,
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config"
}
diff --git a/packages/api/src/router/docker/docker-router.ts b/packages/api/src/router/docker/docker-router.ts
index 0d936bec1..fd19f14ec 100644
--- a/packages/api/src/router/docker/docker-router.ts
+++ b/packages/api/src/router/docker/docker-router.ts
@@ -72,7 +72,7 @@ function sanitizeContainers(
): DockerContainer[] {
return containers.map((container) => {
return {
- name: container.Names[0]?.split("/")[1] || "Unknown",
+ name: container.Names[0]?.split("/")[1] ?? "Unknown",
id: container.Id,
instance: container.instance,
state: container.State as DockerContainerState,
diff --git a/packages/api/src/router/docker/docker-singleton.ts b/packages/api/src/router/docker/docker-singleton.ts
index 072c40925..f95a58418 100644
--- a/packages/api/src/router/docker/docker-singleton.ts
+++ b/packages/api/src/router/docker/docker-singleton.ts
@@ -28,7 +28,7 @@ export class DockerSingleton {
host: `${host}:${ports[i]}`,
instance: new Docker({
host,
- port: parseInt(ports[i] || "", 10),
+ port: parseInt(ports[i] ?? "", 10),
}),
});
return instances;
@@ -41,6 +41,7 @@ export class DockerSingleton {
}
public static getInstance(): DockerInstance[] {
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!DockerSingleton.instances) {
DockerSingleton.instances = new DockerSingleton().createInstances();
}
diff --git a/packages/api/src/router/group.ts b/packages/api/src/router/group.ts
index 17a7749d1..3d0cfe168 100644
--- a/packages/api/src/router/group.ts
+++ b/packages/api/src/router/group.ts
@@ -42,7 +42,7 @@ export const groupRouter = createTRPCRouter({
...group,
members: group.members.map((member) => member.user),
})),
- totalCount: groupCount[0]!.count,
+ totalCount: groupCount[0]?.count ?? 0,
};
}),
getById: protectedProcedure.input(validation.group.byId).query(async ({ input, ctx }) => {
diff --git a/packages/api/src/router/icons.ts b/packages/api/src/router/icons.ts
index e0c3c9a7c..e99918da3 100644
--- a/packages/api/src/router/icons.ts
+++ b/packages/api/src/router/icons.ts
@@ -15,7 +15,7 @@ export const iconsRouter = createTRPCRouter({
name: true,
url: true,
},
- where: input.searchText?.length ?? 0 > 0 ? like(icons.name, `%${input.searchText}%`) : undefined,
+ where: (input.searchText?.length ?? 0) > 0 ? like(icons.name, `%${input.searchText}%`) : undefined,
limit: 5,
},
},
diff --git a/packages/api/src/router/test/app.spec.ts b/packages/api/src/router/test/app.spec.ts
index db9550d0c..1ab6ee559 100644
--- a/packages/api/src/router/test/app.spec.ts
+++ b/packages/api/src/router/test/app.spec.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { describe, expect, test, vi } from "vitest";
import type { Session } from "@homarr/auth";
diff --git a/packages/api/src/router/test/group.spec.ts b/packages/api/src/router/test/group.spec.ts
index 2901ec32b..c91483e72 100644
--- a/packages/api/src/router/test/group.spec.ts
+++ b/packages/api/src/router/test/group.spec.ts
@@ -169,7 +169,7 @@ describe("byId should return group by id including members and permissions", ()
expect(result.id).toBe(groupId);
expect(result.members.length).toBe(1);
- const userKeys = Object.keys(result?.members[0] ?? {});
+ const userKeys = Object.keys(result.members[0] ?? {});
expect(userKeys.length).toBe(4);
expect(["id", "name", "email", "image"].some((key) => userKeys.includes(key)));
expect(result.permissions.length).toBe(1);
diff --git a/packages/api/src/router/test/integration.spec.ts b/packages/api/src/router/test/integration.spec.ts
index 2a68a8c39..9b5b7f6d7 100644
--- a/packages/api/src/router/test/integration.spec.ts
+++ b/packages/api/src/router/test/integration.spec.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { describe, expect, it, vi } from "vitest";
import type { Session } from "@homarr/auth";
diff --git a/packages/api/src/router/test/invite.spec.ts b/packages/api/src/router/test/invite.spec.ts
index 59f2fad68..bcd8c3675 100644
--- a/packages/api/src/router/test/invite.spec.ts
+++ b/packages/api/src/router/test/invite.spec.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { describe, expect, test, vi } from "vitest";
import type { Session } from "@homarr/auth";
diff --git a/packages/api/src/router/user.ts b/packages/api/src/router/user.ts
index 7d3fbd100..a9047f8a2 100644
--- a/packages/api/src/router/user.ts
+++ b/packages/api/src/router/user.ts
@@ -44,13 +44,6 @@ export const userRouter = createTRPCRouter({
});
}
- if (!dbInvite || dbInvite.expirationDate < new Date()) {
- throw new TRPCError({
- code: "FORBIDDEN",
- message: "Invalid invite",
- });
- }
-
await checkUsernameAlreadyTakenAndThrowAsync(ctx.db, input.username);
await createUserAsync(ctx.db, input);
diff --git a/packages/api/src/router/widgets/weather.ts b/packages/api/src/router/widgets/weather.ts
index ab59ef50f..665fdedd4 100644
--- a/packages/api/src/router/widgets/weather.ts
+++ b/packages/api/src/router/widgets/weather.ts
@@ -18,7 +18,7 @@ export const weatherRouter = createTRPCRouter({
maxTemp: weather.daily.temperature_2m_max[index],
minTemp: weather.daily.temperature_2m_min[index],
};
- }) ?? [{ time: 0, weatherCode: 404 }],
+ }),
};
}),
});
diff --git a/packages/api/src/trpc.ts b/packages/api/src/trpc.ts
index 5d231aae4..0248720d3 100644
--- a/packages/api/src/trpc.ts
+++ b/packages/api/src/trpc.ts
@@ -122,7 +122,7 @@ export const protectedProcedure = t.procedure.use(enforceUserIsAuthed);
export const permissionRequiredProcedure = {
requiresPermission: (permission: GroupPermissionKey) => {
return protectedProcedure.use(({ ctx, input, next }) => {
- if (!ctx.session?.user.permissions.includes(permission)) {
+ if (!ctx.session.user.permissions.includes(permission)) {
throw new TRPCError({
code: "FORBIDDEN",
message: "Permission denied",
diff --git a/packages/auth/callbacks.ts b/packages/auth/callbacks.ts
index 3fdeb0c54..be34dcba7 100644
--- a/packages/auth/callbacks.ts
+++ b/packages/auth/callbacks.ts
@@ -44,10 +44,8 @@ export const createSignInCallback =
async ({ user }) => {
if (!isCredentialsRequest) return true;
- if (!user) return true;
-
// https://github.com/nextauthjs/next-auth/issues/6106
- if (!adapter?.createSession) {
+ if (!adapter.createSession) {
return false;
}
@@ -56,6 +54,7 @@ export const createSignInCallback =
await adapter.createSession({
sessionToken,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
userId: user.id!,
expires: sessionExpiry,
});
diff --git a/packages/auth/eslint.config.js b/packages/auth/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/packages/auth/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/packages/auth/package.json b/packages/auth/package.json
index b22f98fc2..2793bce08 100644
--- a/packages/auth/package.json
+++ b/packages/auth/package.json
@@ -16,7 +16,7 @@
"license": "MIT",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -40,15 +40,9 @@
"@homarr/definitions": "workspace:^0.1.0",
"@types/bcrypt": "5.0.2",
"@types/cookies": "0.9.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"prettier": "^3.3.1",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "root": true,
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config"
}
diff --git a/packages/auth/permissions/board-permissions.ts b/packages/auth/permissions/board-permissions.ts
index 35bac53ab..af3b57816 100644
--- a/packages/auth/permissions/board-permissions.ts
+++ b/packages/auth/permissions/board-permissions.ts
@@ -23,14 +23,14 @@ export const constructBoardPermissions = (board: BoardPermissionsProps, session:
const creatorId = "creator" in board ? board.creator?.id : board.creatorId;
return {
- hasFullAccess: session?.user?.id === creatorId || session?.user.permissions.includes("board-full-access"),
+ hasFullAccess: session?.user.id === creatorId || session?.user.permissions.includes("board-full-access"),
hasChangeAccess:
- session?.user?.id === creatorId ||
+ session?.user.id === creatorId ||
board.userPermissions.some(({ permission }) => permission === "board-change") ||
board.groupPermissions.some(({ permission }) => permission === "board-change") ||
session?.user.permissions.includes("board-modify-all"),
hasViewAccess:
- session?.user?.id === creatorId ||
+ session?.user.id === creatorId ||
board.userPermissions.length >= 1 ||
board.groupPermissions.length >= 1 ||
board.isPublic ||
diff --git a/packages/auth/test/callbacks.spec.ts b/packages/auth/test/callbacks.spec.ts
index 1dced2115..ed66f9af4 100644
--- a/packages/auth/test/callbacks.spec.ts
+++ b/packages/auth/test/callbacks.spec.ts
@@ -1,8 +1,9 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
import type { ResponseCookie } from "next/dist/compiled/@edge-runtime/cookies";
import type { ReadonlyRequestCookies } from "next/dist/server/web/spec-extension/adapters/request-cookies";
import { cookies } from "next/headers";
import type { Adapter, AdapterUser } from "@auth/core/adapters";
-import type { Account, User } from "next-auth";
+import type { Account } from "next-auth";
import type { JWT } from "next-auth/jwt";
import { describe, expect, it, test, vi } from "vitest";
@@ -141,21 +142,11 @@ describe("createSignInCallback", () => {
expect(result).toBe(true);
});
- it("should return true if no user", async () => {
- const isCredentialsRequest = true;
- const signInCallback = createSignInCallback(createAdapter(), isCredentialsRequest);
- const result = await signInCallback({
- user: undefined as unknown as User,
- account: {} as Account,
- });
- expect(result).toBe(true);
- });
-
it("should return false if no adapter.createSession", async () => {
const isCredentialsRequest = true;
const signInCallback = createSignInCallback(
// https://github.com/nextauthjs/next-auth/issues/6106
- undefined as unknown as Adapter,
+ { createSession: undefined } as unknown as Adapter,
isCredentialsRequest,
);
const result = await signInCallback({
diff --git a/packages/common/eslint.config.js b/packages/common/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/packages/common/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/packages/common/package.json b/packages/common/package.json
index 31cd7eabb..dd70190d5 100644
--- a/packages/common/package.json
+++ b/packages/common/package.json
@@ -17,7 +17,7 @@
"license": "MIT",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -25,13 +25,8 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config"
}
diff --git a/packages/db/configs/mysql.config.ts b/packages/db/configs/mysql.config.ts
index b3669df13..407fae864 100644
--- a/packages/db/configs/mysql.config.ts
+++ b/packages/db/configs/mysql.config.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
import * as dotenv from "dotenv";
import type { Config } from "drizzle-kit";
diff --git a/packages/db/configs/sqlite.config.ts b/packages/db/configs/sqlite.config.ts
index 919cbfc0b..aba34fe26 100644
--- a/packages/db/configs/sqlite.config.ts
+++ b/packages/db/configs/sqlite.config.ts
@@ -6,6 +6,7 @@ dotenv.config({ path: "../../.env" });
export default {
dialect: "sqlite",
schema: "./schema",
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
dbCredentials: { url: process.env.DB_URL! },
out: "./migrations/sqlite",
} satisfies Config;
diff --git a/packages/db/driver.ts b/packages/db/driver.ts
index 2cea933ea..36a86ece5 100644
--- a/packages/db/driver.ts
+++ b/packages/db/driver.ts
@@ -13,6 +13,7 @@ import * as sqliteSchema from "./schema/sqlite";
type HomarrDatabase = BetterSQLite3Database;
const init = () => {
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!connection) {
switch (process.env.DB_DRIVER) {
case "mysql2":
@@ -48,6 +49,7 @@ const initMySQL2 = () => {
} else {
connection = mysql.createConnection({
host: process.env.DB_HOST,
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
database: process.env.DB_NAME!,
port: Number(process.env.DB_PORT),
user: process.env.DB_USER,
diff --git a/packages/db/eslint.config.js b/packages/db/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/packages/db/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/packages/db/migrations/mysql/migrate.ts b/packages/db/migrations/mysql/migrate.ts
index fd67b7f70..50d495d00 100644
--- a/packages/db/migrations/mysql/migrate.ts
+++ b/packages/db/migrations/mysql/migrate.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { drizzle } from "drizzle-orm/mysql2";
import { migrate } from "drizzle-orm/mysql2/migrator";
import mysql from "mysql2";
diff --git a/packages/db/package.json b/packages/db/package.json
index 79597b7d1..c6bf13ca9 100644
--- a/packages/db/package.json
+++ b/packages/db/package.json
@@ -17,7 +17,7 @@
"build:sqlite": "esbuild migrations/sqlite/migrate.ts --bundle --platform=node --outfile=migrations/sqlite/migrate.cjs",
"build:mysql": "esbuild migrations/mysql/migrate.ts --bundle --platform=node --outfile=migrations/mysql/migrate.cjs",
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"migration:sqlite:generate": "drizzle-kit generate --config ./configs/sqlite.config.ts",
"migration:sqlite:run": "drizzle-kit migrate --config ./configs/sqlite.config.ts",
@@ -44,15 +44,9 @@
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/better-sqlite3": "7.6.10",
"dotenv-cli": "^7.4.2",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"prettier": "^3.3.1",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "root": true,
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config"
}
diff --git a/packages/db/test/schema.spec.ts b/packages/db/test/schema.spec.ts
index 78b8363e2..1d379763a 100644
--- a/packages/db/test/schema.spec.ts
+++ b/packages/db/test/schema.spec.ts
@@ -1,3 +1,4 @@
+/* eslint-disable @typescript-eslint/no-non-null-assertion */
import type { Column, InferSelectModel } from "drizzle-orm";
import type { ForeignKey as MysqlForeignKey, MySqlTableWithColumns } from "drizzle-orm/mysql-core";
import type { ForeignKey as SqliteForeignKey, SQLiteTableWithColumns } from "drizzle-orm/sqlite-core";
diff --git a/packages/definitions/eslint.config.js b/packages/definitions/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/packages/definitions/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/packages/definitions/package.json b/packages/definitions/package.json
index c93c62866..c0c1f04a1 100644
--- a/packages/definitions/package.json
+++ b/packages/definitions/package.json
@@ -16,7 +16,7 @@
"license": "MIT",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -24,14 +24,9 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/common": "workspace:^0.1.0"
diff --git a/packages/definitions/src/integration.ts b/packages/definitions/src/integration.ts
index 3f5650af4..e8e153e01 100644
--- a/packages/definitions/src/integration.ts
+++ b/packages/definitions/src/integration.ts
@@ -115,16 +115,16 @@ export const integrationDefs = {
}
>;
-export const getIconUrl = (integration: IntegrationKind) => integrationDefs[integration]?.iconUrl ?? null;
+export const getIconUrl = (integration: IntegrationKind) => integrationDefs[integration].iconUrl;
export const getIntegrationName = (integration: IntegrationKind) => integrationDefs[integration].name;
export const getDefaultSecretKinds = (integration: IntegrationKind): IntegrationSecretKind[] =>
- integrationDefs[integration]?.secretKinds[0];
+ integrationDefs[integration].secretKinds[0];
export const getAllSecretKindOptions = (
integration: IntegrationKind,
-): [IntegrationSecretKind[], ...IntegrationSecretKind[][]] => integrationDefs[integration]?.secretKinds;
+): [IntegrationSecretKind[], ...IntegrationSecretKind[][]] => integrationDefs[integration].secretKinds;
export const integrationKinds = objectKeys(integrationDefs);
diff --git a/packages/definitions/src/permissions.ts b/packages/definitions/src/permissions.ts
index 827c78df9..8c3eae83c 100644
--- a/packages/definitions/src/permissions.ts
+++ b/packages/definitions/src/permissions.ts
@@ -34,6 +34,7 @@ export const getPermissionsWithParents = (permissions: GroupPermissionKey[]): Gr
const getPermissionsInner = (permissionSet: Set, permissions: GroupPermissionKey[]) => {
permissions.forEach((permission) => {
const children = groupPermissionParents[permission as keyof typeof groupPermissionParents];
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (children) {
getPermissionsInner(permissionSet, children);
}
diff --git a/packages/form/eslint.config.js b/packages/form/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/packages/form/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/packages/form/package.json b/packages/form/package.json
index 208e579ab..2dcae3a56 100644
--- a/packages/form/package.json
+++ b/packages/form/package.json
@@ -2,6 +2,7 @@
"name": "@homarr/form",
"private": true,
"version": "0.1.0",
+ "type": "module",
"exports": {
".": "./index.ts"
},
@@ -15,7 +16,7 @@
"license": "MIT",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -23,14 +24,9 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config",
"dependencies": {
"@mantine/form": "^7.10.1",
diff --git a/packages/icons/eslint.config.js b/packages/icons/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/packages/icons/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/packages/icons/package.json b/packages/icons/package.json
index f3883cad2..eca72229e 100644
--- a/packages/icons/package.json
+++ b/packages/icons/package.json
@@ -16,7 +16,7 @@
"license": "MIT",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -27,13 +27,8 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config"
}
diff --git a/packages/icons/src/repositories/github.icon-repository.ts b/packages/icons/src/repositories/github.icon-repository.ts
index 3523bf930..780f280da 100644
--- a/packages/icons/src/repositories/github.icon-repository.ts
+++ b/packages/icons/src/repositories/github.icon-repository.ts
@@ -32,6 +32,7 @@ export class GitHubIconRepository extends IconRepository {
const fileNameWithExtension = this.getFileNameWithoutExtensionFromPath(treeItem.path);
return {
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
imageUrl: new URL(this.repositoryBlobUrlTemplate!.replace("{0}", treeItem.path)),
fileNameWithExtension: fileNameWithExtension,
local: false,
diff --git a/packages/integrations/eslint.config.js b/packages/integrations/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/packages/integrations/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/packages/integrations/package.json b/packages/integrations/package.json
index 5df87673e..057f79ed5 100644
--- a/packages/integrations/package.json
+++ b/packages/integrations/package.json
@@ -17,7 +17,7 @@
"type": "module",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -25,17 +25,12 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
"dependencies": {
"@homarr/definitions": "workspace:^0.1.0",
"@homarr/validation": "workspace:^0.1.0"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config"
}
diff --git a/packages/log/eslint.config.js b/packages/log/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/packages/log/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/packages/log/package.json b/packages/log/package.json
index 18c403c27..6db63ae59 100644
--- a/packages/log/package.json
+++ b/packages/log/package.json
@@ -2,6 +2,7 @@
"name": "@homarr/log",
"private": true,
"version": "0.1.0",
+ "type": "module",
"exports": {
".": {
"types": "./src/index.d.ts",
@@ -19,7 +20,7 @@
"license": "MIT",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -32,13 +33,8 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config"
}
diff --git a/packages/log/src/override.cjs b/packages/log/src/override.cjs
index c8538f602..8d4c5ca94 100644
--- a/packages/log/src/override.cjs
+++ b/packages/log/src/override.cjs
@@ -1,7 +1,6 @@
void (async () => {
const { logger } = await import("./index.mjs");
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-var-requires
const nextLogger = require("next/dist/build/output/log");
const getWinstonMethodForConsole = (consoleMethod) => {
@@ -37,9 +36,7 @@ void (async () => {
}
};
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
Object.keys(nextLogger.prefixes).forEach((method) => {
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
nextLogger[method] = getWinstonMethodForNext(method);
});
})();
diff --git a/packages/modals/eslint.config.js b/packages/modals/eslint.config.js
new file mode 100644
index 000000000..1df6129af
--- /dev/null
+++ b/packages/modals/eslint.config.js
@@ -0,0 +1,5 @@
+import baseConfig from "@homarr/eslint-config/base";
+import reactConfig from "@homarr/eslint-config/react";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig, ...reactConfig];
diff --git a/packages/modals/package.json b/packages/modals/package.json
index 9736781c6..0f5498be5 100644
--- a/packages/modals/package.json
+++ b/packages/modals/package.json
@@ -2,6 +2,7 @@
"name": "@homarr/modals",
"private": true,
"version": "0.1.0",
+ "type": "module",
"exports": {
".": "./index.ts"
},
@@ -15,7 +16,7 @@
"license": "MIT",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -27,13 +28,8 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config"
}
diff --git a/packages/modals/src/confirm-modal.tsx b/packages/modals/src/confirm-modal.tsx
index d1434b874..9b26d6508 100644
--- a/packages/modals/src/confirm-modal.tsx
+++ b/packages/modals/src/confirm-modal.tsx
@@ -41,7 +41,7 @@ export const ConfirmModal = createModal>(({ act
const handleCancel = useCallback(
async (event: React.MouseEvent) => {
- typeof cancelProps?.onClick === "function" && cancelProps?.onClick(event);
+ typeof cancelProps?.onClick === "function" && cancelProps.onClick(event);
typeof onCancel === "function" && (await onCancel());
closeOnCancel && actions.closeModal();
},
@@ -51,7 +51,7 @@ export const ConfirmModal = createModal>(({ act
const handleConfirm = useCallback(
async (event: React.MouseEvent) => {
setLoading(true);
- typeof confirmProps?.onClick === "function" && confirmProps?.onClick(event);
+ typeof confirmProps?.onClick === "function" && confirmProps.onClick(event);
typeof onConfirm === "function" && (await onConfirm());
closeOnConfirm && actions.closeModal();
setLoading(false);
@@ -65,11 +65,11 @@ export const ConfirmModal = createModal>(({ act
>
diff --git a/packages/modals/src/index.tsx b/packages/modals/src/index.tsx
index 68876a6b6..f3c9e1386 100644
--- a/packages/modals/src/index.tsx
+++ b/packages/modals/src/index.tsx
@@ -138,6 +138,8 @@ export const useModalAction = (modal: TModal) =>
return {
openModal: (innerProps: inferInnerProps, options: OpenModalOptions | void) => {
+ // void actually is undefined
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
context.openModalInner({ modal, innerProps, options: options ?? {} });
},
};
diff --git a/packages/modals/src/reducer.tsx b/packages/modals/src/reducer.tsx
index ab45cb386..ba22f7297 100644
--- a/packages/modals/src/reducer.tsx
+++ b/packages/modals/src/reducer.tsx
@@ -62,7 +62,7 @@ export const modalReducer = (state: ModalsState, action: OpenAction | CloseActio
const remainingModals = state.modals.filter((modal) => modal.id !== action.modalId);
return {
- current: remainingModals[remainingModals.length - 1] || state.current,
+ current: remainingModals[remainingModals.length - 1] ?? state.current,
modals: remainingModals,
};
}
diff --git a/packages/notifications/eslint.config.js b/packages/notifications/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/packages/notifications/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/packages/notifications/package.json b/packages/notifications/package.json
index 484472865..d321cec7c 100644
--- a/packages/notifications/package.json
+++ b/packages/notifications/package.json
@@ -2,6 +2,7 @@
"name": "@homarr/notifications",
"private": true,
"version": "0.1.0",
+ "type": "module",
"exports": {
".": "./index.ts",
"./styles.css": "./src/styles.css"
@@ -16,7 +17,7 @@
"license": "MIT",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -24,17 +25,12 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
"dependencies": {
"@mantine/notifications": "^7.10.1",
"@homarr/ui": "workspace:^0.1.0"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config"
}
diff --git a/packages/ping/eslint.config.js b/packages/ping/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/packages/ping/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/packages/ping/package.json b/packages/ping/package.json
index 7279a3ef7..e4246da6d 100644
--- a/packages/ping/package.json
+++ b/packages/ping/package.json
@@ -16,7 +16,7 @@
"type": "module",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -28,13 +28,8 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config"
}
diff --git a/packages/redis/eslint.config.js b/packages/redis/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/packages/redis/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/packages/redis/package.json b/packages/redis/package.json
index 90be8eef6..a73cc63ae 100644
--- a/packages/redis/package.json
+++ b/packages/redis/package.json
@@ -16,7 +16,7 @@
"type": "module",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -30,13 +30,8 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config"
}
diff --git a/packages/server-settings/eslint.config.js b/packages/server-settings/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/packages/server-settings/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/packages/server-settings/package.json b/packages/server-settings/package.json
index 8e0ffc6c8..9e35567f9 100644
--- a/packages/server-settings/package.json
+++ b/packages/server-settings/package.json
@@ -16,7 +16,7 @@
"license": "MIT",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -24,13 +24,8 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config"
}
diff --git a/packages/spotlight/eslint.config.js b/packages/spotlight/eslint.config.js
new file mode 100644
index 000000000..1df6129af
--- /dev/null
+++ b/packages/spotlight/eslint.config.js
@@ -0,0 +1,5 @@
+import baseConfig from "@homarr/eslint-config/base";
+import reactConfig from "@homarr/eslint-config/react";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig, ...reactConfig];
diff --git a/packages/spotlight/package.json b/packages/spotlight/package.json
index 218418b3f..770da472a 100644
--- a/packages/spotlight/package.json
+++ b/packages/spotlight/package.json
@@ -2,6 +2,7 @@
"name": "@homarr/spotlight",
"private": true,
"version": "0.1.0",
+ "type": "module",
"exports": {
".": "./index.ts",
"./styles.css": "./src/styles.css"
@@ -16,7 +17,7 @@
"license": "MIT",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -24,14 +25,9 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config",
"dependencies": {
"@mantine/spotlight": "^7.10.1",
diff --git a/packages/translation/eslint.config.js b/packages/translation/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/packages/translation/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/packages/translation/package.json b/packages/translation/package.json
index 506e5e048..65caf72c3 100644
--- a/packages/translation/package.json
+++ b/packages/translation/package.json
@@ -2,6 +2,7 @@
"name": "@homarr/translation",
"private": true,
"version": "0.1.0",
+ "type": "module",
"exports": {
".": "./index.ts",
"./client": "./src/client.ts",
@@ -18,7 +19,7 @@
"license": "MIT",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -26,14 +27,9 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config",
"dependencies": {
"next-international": "^1.2.4"
diff --git a/packages/ui/eslint.config.js b/packages/ui/eslint.config.js
new file mode 100644
index 000000000..1df6129af
--- /dev/null
+++ b/packages/ui/eslint.config.js
@@ -0,0 +1,5 @@
+import baseConfig from "@homarr/eslint-config/base";
+import reactConfig from "@homarr/eslint-config/react";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig, ...reactConfig];
diff --git a/packages/ui/package.json b/packages/ui/package.json
index 783154b52..ba13d2751 100644
--- a/packages/ui/package.json
+++ b/packages/ui/package.json
@@ -2,6 +2,7 @@
"name": "@homarr/ui",
"private": true,
"version": "0.1.0",
+ "type": "module",
"exports": {
".": "./index.ts",
"./styles.css": "./src/styles.css"
@@ -16,7 +17,7 @@
"license": "MIT",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -25,17 +26,12 @@
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/css-modules": "^1.0.5",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
"dependencies": {
"@homarr/log": "workspace:^0.1.0",
"@homarr/translation": "workspace:^0.1.0"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config"
}
diff --git a/packages/ui/src/components/text-multi-select.tsx b/packages/ui/src/components/text-multi-select.tsx
index e63d570dc..5561d7baf 100644
--- a/packages/ui/src/components/text-multi-select.tsx
+++ b/packages/ui/src/components/text-multi-select.tsx
@@ -72,6 +72,7 @@ export const TextMultiSelect = ({ label, value = [], onChange, onBlur, onFocus,
onKeyDown={(event) => {
if (event.key === "Backspace" && search.length === 0) {
event.preventDefault();
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
handleValueRemove(value.at(-1)!);
}
}}
diff --git a/packages/validation/eslint.config.js b/packages/validation/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/packages/validation/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/packages/validation/package.json b/packages/validation/package.json
index fa45fba35..0f9f72d07 100644
--- a/packages/validation/package.json
+++ b/packages/validation/package.json
@@ -17,7 +17,7 @@
"license": "MIT",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -25,14 +25,9 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config",
"dependencies": {
"zod": "^3.23.8",
diff --git a/packages/validation/src/enums.ts b/packages/validation/src/enums.ts
index f9e59ef89..988198adc 100644
--- a/packages/validation/src/enums.ts
+++ b/packages/validation/src/enums.ts
@@ -3,7 +3,9 @@ import { z } from "zod";
type CouldBeReadonlyArray = T[] | readonly T[];
export const zodEnumFromArray = (array: CouldBeReadonlyArray) =>
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
z.enum([array[0]!, ...array.slice(1)]);
export const zodUnionFromArray = (array: CouldBeReadonlyArray) =>
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
z.union([array[0]!, array[1]!, ...array.slice(2)]);
diff --git a/packages/validation/src/form/i18n.ts b/packages/validation/src/form/i18n.ts
index 08f97e988..5a8e4f65d 100644
--- a/packages/validation/src/form/i18n.ts
+++ b/packages/validation/src/form/i18n.ts
@@ -13,7 +13,7 @@ export const zodErrorMap = <
const error = handleZodError(issue, ctx);
if ("message" in error && error.message)
return {
- message: error.message ?? ctx.defaultError,
+ message: error.message,
};
return {
message: t(error.key ? `common.zod.${error.key}` : "common.zod.errors.default", error.params ?? {}),
diff --git a/packages/widgets/eslint.config.js b/packages/widgets/eslint.config.js
new file mode 100644
index 000000000..1df6129af
--- /dev/null
+++ b/packages/widgets/eslint.config.js
@@ -0,0 +1,5 @@
+import baseConfig from "@homarr/eslint-config/base";
+import reactConfig from "@homarr/eslint-config/react";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig, ...reactConfig];
diff --git a/packages/widgets/package.json b/packages/widgets/package.json
index 42ffa2132..e97317dfd 100644
--- a/packages/widgets/package.json
+++ b/packages/widgets/package.json
@@ -2,6 +2,7 @@
"name": "@homarr/widgets",
"private": true,
"version": "0.1.0",
+ "type": "module",
"exports": {
".": "./index.ts",
"./errors": "./src/errors/component.tsx"
@@ -16,7 +17,7 @@
"license": "MIT",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -26,14 +27,9 @@
"@homarr/tsconfig": "workspace:^0.1.0",
"@types/prismjs": "^1.26.4",
"@types/video.js": "^7.3.58",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config",
"dependencies": {
"@homarr/api": "workspace:^0.1.0",
diff --git a/packages/widgets/src/_inputs/widget-multiselect-input.tsx b/packages/widgets/src/_inputs/widget-multiselect-input.tsx
index 9f3db9e92..6793dade3 100644
--- a/packages/widgets/src/_inputs/widget-multiselect-input.tsx
+++ b/packages/widgets/src/_inputs/widget-multiselect-input.tsx
@@ -20,7 +20,7 @@ export const WidgetMultiSelectInput = ({ property, kind, options }: CommonWidget
? option
: {
value: option.value,
- label: translateIfNecessary(t, option.label)!,
+ label: translateIfNecessary(t, option.label) ?? option.value,
},
)}
description={options.withDescription ? t("description") : undefined}
diff --git a/packages/widgets/src/_inputs/widget-select-input.tsx b/packages/widgets/src/_inputs/widget-select-input.tsx
index fd1df1d8f..ec07b2932 100644
--- a/packages/widgets/src/_inputs/widget-select-input.tsx
+++ b/packages/widgets/src/_inputs/widget-select-input.tsx
@@ -36,7 +36,7 @@ export const WidgetSelectInput = ({ property, kind, options }: CommonWidgetInput
? option
: {
value: option.value,
- label: translateIfNecessary(t, option.label)!,
+ label: translateIfNecessary(t, option.label) ?? option.value,
},
)}
description={options.withDescription ? tWidget("description") : undefined}
diff --git a/packages/widgets/src/app/component.tsx b/packages/widgets/src/app/component.tsx
index 0c47588dc..8838e6436 100644
--- a/packages/widgets/src/app/component.tsx
+++ b/packages/widgets/src/app/component.tsx
@@ -27,7 +27,7 @@ export default function AppWidget({ options, serverData, isEditMode, width, heig
{
initialData:
// We need to check if the id's match because otherwise the same initialData for a changed id will be used
- serverData?.app?.id === options.appId ? serverData?.app : undefined,
+ serverData?.app?.id === options.appId ? serverData.app : undefined,
refetchOnMount: false,
refetchOnWindowFocus: false,
refetchOnReconnect: false,
@@ -54,12 +54,12 @@ export default function AppWidget({ options, serverData, isEditMode, width, heig
? [
{
id: `app-${options.appId}`,
- title: app?.name,
- description: app?.description ?? "",
- icon: app?.iconUrl,
+ title: app.name,
+ description: app.description ?? "",
+ icon: app.iconUrl,
group: "app",
type: "link",
- href: app?.href,
+ href: app.href,
openInNewTab: options.openInNewTab,
},
]
diff --git a/packages/widgets/src/modals/widget-edit-modal.tsx b/packages/widgets/src/modals/widget-edit-modal.tsx
index 10dc57a02..4330e2752 100644
--- a/packages/widgets/src/modals/widget-edit-modal.tsx
+++ b/packages/widgets/src/modals/widget-edit-modal.tsx
@@ -62,6 +62,7 @@ export const WidgetEditModal = createModal>(({ actions, i
{Object.entries(definition.options).map(([key, value]: [string, OptionsBuilderResult[string]]) => {
const Input = getInputForType(value.type);
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (!Input || value.shouldHide?.(form.values.options as never)) {
return null;
}
diff --git a/packages/widgets/src/notebook/notebook.tsx b/packages/widgets/src/notebook/notebook.tsx
index e7967d81f..7ca935bc6 100644
--- a/packages/widgets/src/notebook/notebook.tsx
+++ b/packages/widgets/src/notebook/notebook.tsx
@@ -303,7 +303,9 @@ export function Notebook({ options, isEditMode, boardId, itemId }: WidgetCompone
- {(editor?.isActive("taskList") || editor?.isActive("bulletList") || editor?.isActive("orderedList")) && (
+ {(Boolean(editor?.isActive("taskList")) ||
+ Boolean(editor?.isActive("bulletList")) ||
+ Boolean(editor?.isActive("orderedList"))) && (
<>
@@ -680,7 +682,7 @@ function ListIndentIncrease() {
}, [editor, itemType]);
editor?.on("selectionUpdate", ({ editor }) => {
- setItemType(editor?.isActive("taskItem") ? "taskItem" : "listItem");
+ setItemType(editor.isActive("taskItem") ? "taskItem" : "listItem");
});
return (
@@ -704,7 +706,7 @@ function ListIndentDecrease() {
}, [editor, itemType]);
editor?.on("selectionUpdate", ({ editor }) => {
- setItemType(editor?.isActive("taskItem") ? "taskItem" : "listItem");
+ setItemType(editor.isActive("taskItem") ? "taskItem" : "listItem");
});
return (
diff --git a/packages/widgets/src/widget-integration-select.tsx b/packages/widgets/src/widget-integration-select.tsx
index 5014034e0..39bef4d2d 100644
--- a/packages/widgets/src/widget-integration-select.tsx
+++ b/packages/widgets/src/widget-integration-select.tsx
@@ -98,6 +98,7 @@ export const WidgetIntegrationSelect = ({
if (event.key !== "Backspace") return;
event.preventDefault();
+ // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
handleValueRemove(multiSelectValues[multiSelectValues.length - 1]!);
}}
/>
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index bfaa0f5f0..e975568bf 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -233,8 +233,8 @@ importers:
specifier: ^8.2.2
version: 8.2.2
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
node-loader:
specifier: ^2.0.0
version: 2.0.0(webpack@5.91.0)
@@ -309,8 +309,8 @@ importers:
specifier: ^7.4.2
version: 7.4.2
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
prettier:
specifier: ^3.3.1
version: 3.3.1
@@ -367,8 +367,8 @@ importers:
specifier: ^8.5.10
version: 8.5.10
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
prettier:
specifier: ^3.3.1
version: 3.3.1
@@ -404,8 +404,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -471,8 +471,8 @@ importers:
specifier: ^3.3.29
version: 3.3.29
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
prettier:
specifier: ^3.3.1
version: 3.3.1
@@ -535,8 +535,8 @@ importers:
specifier: 0.9.0
version: 0.9.0
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
prettier:
specifier: ^3.3.1
version: 3.3.1
@@ -556,8 +556,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -605,8 +605,8 @@ importers:
specifier: ^7.4.2
version: 7.4.2
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
prettier:
specifier: ^3.3.1
version: 3.3.1
@@ -630,8 +630,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -658,8 +658,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -680,8 +680,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -705,8 +705,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -733,8 +733,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -758,8 +758,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -783,8 +783,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -808,8 +808,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -839,8 +839,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -857,8 +857,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -885,8 +885,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -907,8 +907,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -935,8 +935,8 @@ importers:
specifier: ^1.0.5
version: 1.0.5
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -963,8 +963,8 @@ importers:
specifier: workspace:^0.1.0
version: link:../../tooling/typescript
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -1078,8 +1078,8 @@ importers:
specifier: ^7.3.58
version: 7.3.58
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -1089,30 +1089,27 @@ importers:
'@next/eslint-plugin-next':
specifier: ^14.2.3
version: 14.2.3
- '@typescript-eslint/eslint-plugin':
- specifier: ^7.12.0
- version: 7.12.0(@typescript-eslint/parser@7.12.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)
- '@typescript-eslint/parser':
- specifier: ^7.12.0
- version: 7.12.0(eslint@8.57.0)(typescript@5.4.5)
eslint-config-prettier:
specifier: ^9.1.0
- version: 9.1.0(eslint@8.57.0)
+ version: 9.1.0(eslint@9.4.0)
eslint-config-turbo:
specifier: ^2.0.3
- version: 2.0.3(eslint@8.57.0)
+ version: 2.0.3(eslint@9.4.0)
eslint-plugin-import:
specifier: ^2.29.1
- version: 2.29.1(@typescript-eslint/parser@7.12.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)
+ version: 2.29.1(@typescript-eslint/parser@7.12.0(eslint@9.4.0)(typescript@5.4.5))(eslint@9.4.0)
eslint-plugin-jsx-a11y:
specifier: ^6.8.0
- version: 6.8.0(eslint@8.57.0)
+ version: 6.8.0(eslint@9.4.0)
eslint-plugin-react:
specifier: ^7.34.2
- version: 7.34.2(eslint@8.57.0)
+ version: 7.34.2(eslint@9.4.0)
eslint-plugin-react-hooks:
specifier: ^4.6.2
- version: 4.6.2(eslint@8.57.0)
+ version: 4.6.2(eslint@9.4.0)
+ typescript-eslint:
+ specifier: ^7.12.0
+ version: 7.12.0(eslint@9.4.0)(typescript@5.4.5)
devDependencies:
'@homarr/prettier-config':
specifier: workspace:^0.1.0
@@ -1120,12 +1117,9 @@ importers:
'@homarr/tsconfig':
specifier: workspace:^0.1.0
version: link:../typescript
- '@types/eslint':
- specifier: ^8.56.10
- version: 8.56.10
eslint:
- specifier: ^8.57.0
- version: 8.57.0
+ specifier: ^9.4.0
+ version: 9.4.0
typescript:
specifier: ^5.4.5
version: 5.4.5
@@ -1826,13 +1820,21 @@ packages:
resolution: {integrity: sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA==}
engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0}
- '@eslint/eslintrc@2.1.4':
- resolution: {integrity: sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ '@eslint/config-array@0.15.1':
+ resolution: {integrity: sha512-K4gzNq+yymn/EVsXYmf+SBcBro8MTf+aXJZUphM96CdzUEr+ClGDvAbpmaEK+cGVigVXIgs9gNmvHAlrzzY5JQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/js@8.57.0':
- resolution: {integrity: sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ '@eslint/eslintrc@3.1.0':
+ resolution: {integrity: sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/js@9.4.0':
+ resolution: {integrity: sha512-fdI7VJjP3Rvc70lC4xkFXHB0fiPeojiL1PxVG6t1ZvXQrarj893PweuBTujxDUFk0Fxj4R7PIIAZ/aiiyZPZcg==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ '@eslint/object-schema@2.1.3':
+ resolution: {integrity: sha512-HAbhAYKfsAC2EkTqve00ibWIZlaU74Z1EHwAjYr4PXF0YU2VEA1zSIKSSpKszRLRWwHzzRZXvK632u+uXzvsvw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@floating-ui/core@1.6.0':
resolution: {integrity: sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==}
@@ -1858,16 +1860,13 @@ packages:
'@homarr/gridstack@1.0.0':
resolution: {integrity: sha512-KM9024BipLD9BmtM6jHI8OKLZ1Iy4vZdTfU53ww4qEda/330XQYhIC2SBcQgkNnDB2MTkn/laNSO5gTy+lJg9Q==}
- '@humanwhocodes/config-array@0.11.14':
- resolution: {integrity: sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==}
- engines: {node: '>=10.10.0'}
-
'@humanwhocodes/module-importer@1.0.1':
resolution: {integrity: sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==}
engines: {node: '>=12.22'}
- '@humanwhocodes/object-schema@2.0.2':
- resolution: {integrity: sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==}
+ '@humanwhocodes/retry@0.3.0':
+ resolution: {integrity: sha512-d2CGZR2o7fS6sWB7DG/3a95bGKQyHMACZ5aW8qGkkqQpUoZV6C0X7Pc7l4ZNMZkfNBf4VWNe9E1jRsf0G146Ew==}
+ engines: {node: '>=18.18'}
'@ianvs/prettier-plugin-sort-imports@4.2.1':
resolution: {integrity: sha512-NKN1LVFWUDGDGr3vt+6Ey3qPeN/163uR1pOPAlkWpgvAqgxQ6kSdUf1F0it8aHUtKRUzEGcK38Wxd07O61d7+Q==}
@@ -2704,9 +2703,6 @@ packages:
'@umami/node@0.3.0':
resolution: {integrity: sha512-+1cZ7o7jVN8oXDYZRqigfLHrWbEv5vtGWjB7blfVH1QUa+DRmWB6GfhMZtE2aSW+P9ACal8ZW7xD2PCAejlNCQ==}
- '@ungap/structured-clone@1.2.0':
- resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==}
-
'@videojs/http-streaming@3.12.1':
resolution: {integrity: sha512-rpB5AMt0QZ9bMXzwiWhynF2NLNnm5g2DZjPOFX6OoFqqXhbe2ngY2nqm9lLRhRVe22YeysQCmAlvBNwGuWFI8Q==}
engines: {node: '>=8', npm: '>=5'}
@@ -3410,10 +3406,6 @@ packages:
resolution: {integrity: sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==}
engines: {node: '>=0.10.0'}
- doctrine@3.0.0:
- resolution: {integrity: sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==}
- engines: {node: '>=6.0.0'}
-
dom-helpers@5.2.1:
resolution: {integrity: sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==}
@@ -3714,22 +3706,26 @@ packages:
resolution: {integrity: sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==}
engines: {node: '>=8.0.0'}
- eslint-scope@7.2.2:
- resolution: {integrity: sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ eslint-scope@8.0.1:
+ resolution: {integrity: sha512-pL8XjgP4ZOmmwfFE8mEhSxA7ZY4C+LWyqjQ3o4yWkkmD0qcMT9kkW3zWHOczhWcjTSgqycYAgwSlXvZltv65og==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
eslint-visitor-keys@3.4.3:
resolution: {integrity: sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
- eslint@8.57.0:
- resolution: {integrity: sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ eslint-visitor-keys@4.0.0:
+ resolution: {integrity: sha512-OtIRv/2GyiF6o/d8K7MYKKbXrOUBIK6SfkIRM4Z0dY3w+LiQ0vy3F57m0Z71bjbyeiWFiHJ8brqnmE6H6/jEuw==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
+
+ eslint@9.4.0:
+ resolution: {integrity: sha512-sjc7Y8cUD1IlwYcTS9qPSvGjAC8Ne9LctpxKKu3x/1IC9bnOg98Zy6GxEJUfr1NojMgVPlyANXYns8oE2c1TAA==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
hasBin: true
- espree@9.6.1:
- resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==}
- engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
+ espree@10.0.1:
+ resolution: {integrity: sha512-MWkrWZbJsL2UwnjxTX3gG8FneachS/Mwg7tdGXce011sJd5b0JG54vat5KHnfSBODZ3Wvzd2WnjxyzsRoVv+ww==}
+ engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
esprima@4.0.1:
resolution: {integrity: sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==}
@@ -3805,9 +3801,9 @@ packages:
resolution: {integrity: sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==}
engines: {node: '>=8'}
- file-entry-cache@6.0.1:
- resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==}
- engines: {node: ^10.12.0 || >=12.0.0}
+ file-entry-cache@8.0.0:
+ resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==}
+ engines: {node: '>=16.0.0'}
file-uri-to-path@1.0.0:
resolution: {integrity: sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==}
@@ -3823,9 +3819,9 @@ packages:
flag-icons@7.2.3:
resolution: {integrity: sha512-X2gUdteNuqdNqob2KKTJTS+ZCvyWeLCtDz9Ty8uJP17Y4o82Y+U/Vd4JNrdwTAjagYsRznOn9DZ+E/Q52qbmqg==}
- flat-cache@3.2.0:
- resolution: {integrity: sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==}
- engines: {node: ^10.12.0 || >=12.0.0}
+ flat-cache@4.0.1:
+ resolution: {integrity: sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==}
+ engines: {node: '>=16'}
flatted@3.2.9:
resolution: {integrity: sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==}
@@ -3958,9 +3954,9 @@ packages:
resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==}
engines: {node: '>=4'}
- globals@13.24.0:
- resolution: {integrity: sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==}
- engines: {node: '>=8'}
+ globals@14.0.0:
+ resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==}
+ engines: {node: '>=18'}
globalthis@1.0.3:
resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==}
@@ -5841,10 +5837,6 @@ packages:
resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==}
engines: {node: '>=4'}
- type-fest@0.20.2:
- resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==}
- engines: {node: '>=10'}
-
type-fest@0.21.3:
resolution: {integrity: sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==}
engines: {node: '>=10'}
@@ -5888,6 +5880,16 @@ packages:
resolution: {integrity: sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==}
engines: {node: '>= 0.4'}
+ typescript-eslint@7.12.0:
+ resolution: {integrity: sha512-D6HKNbQcnNu3BaN4HkQCR16tgG8Q2AMUWPgvhrJksOXu+d6ys07yC06ONiV2kcsEfWC22voB6C3PvK2MqlBZ7w==}
+ engines: {node: ^18.18.0 || >=20.0.0}
+ peerDependencies:
+ eslint: ^8.56.0
+ typescript: '*'
+ peerDependenciesMeta:
+ typescript:
+ optional: true
+
typescript@5.4.5:
resolution: {integrity: sha512-vcI4UpRgg81oIRUFwR0WSIHKt11nJ7SAVlYNIu+QpqeyXP+gpQJy/Z4+F0aGxSE4MqwjyXvW/TzgkLAx2AGHwQ==}
engines: {node: '>=14.17'}
@@ -6783,19 +6785,27 @@ snapshots:
'@esbuild/win32-x64@0.20.2':
optional: true
- '@eslint-community/eslint-utils@4.4.0(eslint@8.57.0)':
+ '@eslint-community/eslint-utils@4.4.0(eslint@9.4.0)':
dependencies:
- eslint: 8.57.0
+ eslint: 9.4.0
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.10.0': {}
- '@eslint/eslintrc@2.1.4':
+ '@eslint/config-array@0.15.1':
+ dependencies:
+ '@eslint/object-schema': 2.1.3
+ debug: 4.3.4
+ minimatch: 3.1.2
+ transitivePeerDependencies:
+ - supports-color
+
+ '@eslint/eslintrc@3.1.0':
dependencies:
ajv: 6.12.6
debug: 4.3.4
- espree: 9.6.1
- globals: 13.24.0
+ espree: 10.0.1
+ globals: 14.0.0
ignore: 5.3.1
import-fresh: 3.3.0
js-yaml: 4.1.0
@@ -6804,7 +6814,9 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@eslint/js@8.57.0': {}
+ '@eslint/js@9.4.0': {}
+
+ '@eslint/object-schema@2.1.3': {}
'@floating-ui/core@1.6.0':
dependencies:
@@ -6833,17 +6845,9 @@ snapshots:
'@homarr/gridstack@1.0.0': {}
- '@humanwhocodes/config-array@0.11.14':
- dependencies:
- '@humanwhocodes/object-schema': 2.0.2
- debug: 4.3.4
- minimatch: 3.1.2
- transitivePeerDependencies:
- - supports-color
-
'@humanwhocodes/module-importer@1.0.1': {}
- '@humanwhocodes/object-schema@2.0.2': {}
+ '@humanwhocodes/retry@0.3.0': {}
'@ianvs/prettier-plugin-sort-imports@4.2.1(prettier@3.3.1)':
dependencies:
@@ -7637,15 +7641,15 @@ snapshots:
dependencies:
'@types/node': 20.14.2
- '@typescript-eslint/eslint-plugin@7.12.0(@typescript-eslint/parser@7.12.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)':
+ '@typescript-eslint/eslint-plugin@7.12.0(@typescript-eslint/parser@7.12.0(eslint@9.4.0)(typescript@5.4.5))(eslint@9.4.0)(typescript@5.4.5)':
dependencies:
'@eslint-community/regexpp': 4.10.0
- '@typescript-eslint/parser': 7.12.0(eslint@8.57.0)(typescript@5.4.5)
+ '@typescript-eslint/parser': 7.12.0(eslint@9.4.0)(typescript@5.4.5)
'@typescript-eslint/scope-manager': 7.12.0
- '@typescript-eslint/type-utils': 7.12.0(eslint@8.57.0)(typescript@5.4.5)
- '@typescript-eslint/utils': 7.12.0(eslint@8.57.0)(typescript@5.4.5)
+ '@typescript-eslint/type-utils': 7.12.0(eslint@9.4.0)(typescript@5.4.5)
+ '@typescript-eslint/utils': 7.12.0(eslint@9.4.0)(typescript@5.4.5)
'@typescript-eslint/visitor-keys': 7.12.0
- eslint: 8.57.0
+ eslint: 9.4.0
graphemer: 1.4.0
ignore: 5.3.1
natural-compare: 1.4.0
@@ -7655,14 +7659,14 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@7.12.0(eslint@8.57.0)(typescript@5.4.5)':
+ '@typescript-eslint/parser@7.12.0(eslint@9.4.0)(typescript@5.4.5)':
dependencies:
'@typescript-eslint/scope-manager': 7.12.0
'@typescript-eslint/types': 7.12.0
'@typescript-eslint/typescript-estree': 7.12.0(typescript@5.4.5)
'@typescript-eslint/visitor-keys': 7.12.0
debug: 4.3.4
- eslint: 8.57.0
+ eslint: 9.4.0
optionalDependencies:
typescript: 5.4.5
transitivePeerDependencies:
@@ -7673,12 +7677,12 @@ snapshots:
'@typescript-eslint/types': 7.12.0
'@typescript-eslint/visitor-keys': 7.12.0
- '@typescript-eslint/type-utils@7.12.0(eslint@8.57.0)(typescript@5.4.5)':
+ '@typescript-eslint/type-utils@7.12.0(eslint@9.4.0)(typescript@5.4.5)':
dependencies:
'@typescript-eslint/typescript-estree': 7.12.0(typescript@5.4.5)
- '@typescript-eslint/utils': 7.12.0(eslint@8.57.0)(typescript@5.4.5)
+ '@typescript-eslint/utils': 7.12.0(eslint@9.4.0)(typescript@5.4.5)
debug: 4.3.4
- eslint: 8.57.0
+ eslint: 9.4.0
ts-api-utils: 1.3.0(typescript@5.4.5)
optionalDependencies:
typescript: 5.4.5
@@ -7702,13 +7706,13 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@7.12.0(eslint@8.57.0)(typescript@5.4.5)':
+ '@typescript-eslint/utils@7.12.0(eslint@9.4.0)(typescript@5.4.5)':
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
+ '@eslint-community/eslint-utils': 4.4.0(eslint@9.4.0)
'@typescript-eslint/scope-manager': 7.12.0
'@typescript-eslint/types': 7.12.0
'@typescript-eslint/typescript-estree': 7.12.0(typescript@5.4.5)
- eslint: 8.57.0
+ eslint: 9.4.0
transitivePeerDependencies:
- supports-color
- typescript
@@ -7720,8 +7724,6 @@ snapshots:
'@umami/node@0.3.0': {}
- '@ungap/structured-clone@1.2.0': {}
-
'@videojs/http-streaming@3.12.1(video.js@8.12.0)':
dependencies:
'@babel/runtime': 7.23.9
@@ -8554,10 +8556,6 @@ snapshots:
dependencies:
esutils: 2.0.3
- doctrine@3.0.0:
- dependencies:
- esutils: 2.0.3
-
dom-helpers@5.2.1:
dependencies:
'@babel/runtime': 7.23.9
@@ -8883,14 +8881,14 @@ snapshots:
optionalDependencies:
source-map: 0.6.1
- eslint-config-prettier@9.1.0(eslint@8.57.0):
+ eslint-config-prettier@9.1.0(eslint@9.4.0):
dependencies:
- eslint: 8.57.0
+ eslint: 9.4.0
- eslint-config-turbo@2.0.3(eslint@8.57.0):
+ eslint-config-turbo@2.0.3(eslint@9.4.0):
dependencies:
- eslint: 8.57.0
- eslint-plugin-turbo: 2.0.3(eslint@8.57.0)
+ eslint: 9.4.0
+ eslint-plugin-turbo: 2.0.3(eslint@9.4.0)
eslint-import-resolver-node@0.3.9:
dependencies:
@@ -8900,17 +8898,17 @@ snapshots:
transitivePeerDependencies:
- supports-color
- eslint-module-utils@2.8.0(@typescript-eslint/parser@7.12.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0):
+ eslint-module-utils@2.8.0(@typescript-eslint/parser@7.12.0(eslint@9.4.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint@9.4.0):
dependencies:
debug: 3.2.7
optionalDependencies:
- '@typescript-eslint/parser': 7.12.0(eslint@8.57.0)(typescript@5.4.5)
- eslint: 8.57.0
+ '@typescript-eslint/parser': 7.12.0(eslint@9.4.0)(typescript@5.4.5)
+ eslint: 9.4.0
eslint-import-resolver-node: 0.3.9
transitivePeerDependencies:
- supports-color
- eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.12.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0):
+ eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.12.0(eslint@9.4.0)(typescript@5.4.5))(eslint@9.4.0):
dependencies:
array-includes: 3.1.7
array.prototype.findlastindex: 1.2.4
@@ -8918,9 +8916,9 @@ snapshots:
array.prototype.flatmap: 1.3.2
debug: 3.2.7
doctrine: 2.1.0
- eslint: 8.57.0
+ eslint: 9.4.0
eslint-import-resolver-node: 0.3.9
- eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.12.0(eslint@8.57.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint@8.57.0)
+ eslint-module-utils: 2.8.0(@typescript-eslint/parser@7.12.0(eslint@9.4.0)(typescript@5.4.5))(eslint-import-resolver-node@0.3.9)(eslint@9.4.0)
hasown: 2.0.1
is-core-module: 2.13.1
is-glob: 4.0.3
@@ -8931,13 +8929,13 @@ snapshots:
semver: 6.3.1
tsconfig-paths: 3.15.0
optionalDependencies:
- '@typescript-eslint/parser': 7.12.0(eslint@8.57.0)(typescript@5.4.5)
+ '@typescript-eslint/parser': 7.12.0(eslint@9.4.0)(typescript@5.4.5)
transitivePeerDependencies:
- eslint-import-resolver-typescript
- eslint-import-resolver-webpack
- supports-color
- eslint-plugin-jsx-a11y@6.8.0(eslint@8.57.0):
+ eslint-plugin-jsx-a11y@6.8.0(eslint@9.4.0):
dependencies:
'@babel/runtime': 7.23.9
aria-query: 5.3.0
@@ -8949,7 +8947,7 @@ snapshots:
damerau-levenshtein: 1.0.8
emoji-regex: 9.2.2
es-iterator-helpers: 1.0.17
- eslint: 8.57.0
+ eslint: 9.4.0
hasown: 2.0.1
jsx-ast-utils: 3.3.5
language-tags: 1.0.9
@@ -8957,11 +8955,11 @@ snapshots:
object.entries: 1.1.7
object.fromentries: 2.0.7
- eslint-plugin-react-hooks@4.6.2(eslint@8.57.0):
+ eslint-plugin-react-hooks@4.6.2(eslint@9.4.0):
dependencies:
- eslint: 8.57.0
+ eslint: 9.4.0
- eslint-plugin-react@7.34.2(eslint@8.57.0):
+ eslint-plugin-react@7.34.2(eslint@9.4.0):
dependencies:
array-includes: 3.1.8
array.prototype.findlast: 1.2.5
@@ -8970,7 +8968,7 @@ snapshots:
array.prototype.tosorted: 1.1.3
doctrine: 2.1.0
es-iterator-helpers: 1.0.19
- eslint: 8.57.0
+ eslint: 9.4.0
estraverse: 5.3.0
jsx-ast-utils: 3.3.5
minimatch: 3.1.2
@@ -8983,55 +8981,53 @@ snapshots:
semver: 6.3.1
string.prototype.matchall: 4.0.11
- eslint-plugin-turbo@2.0.3(eslint@8.57.0):
+ eslint-plugin-turbo@2.0.3(eslint@9.4.0):
dependencies:
dotenv: 16.0.3
- eslint: 8.57.0
+ eslint: 9.4.0
eslint-scope@5.1.1:
dependencies:
esrecurse: 4.3.0
estraverse: 4.3.0
- eslint-scope@7.2.2:
+ eslint-scope@8.0.1:
dependencies:
esrecurse: 4.3.0
estraverse: 5.3.0
eslint-visitor-keys@3.4.3: {}
- eslint@8.57.0:
+ eslint-visitor-keys@4.0.0: {}
+
+ eslint@9.4.0:
dependencies:
- '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0)
+ '@eslint-community/eslint-utils': 4.4.0(eslint@9.4.0)
'@eslint-community/regexpp': 4.10.0
- '@eslint/eslintrc': 2.1.4
- '@eslint/js': 8.57.0
- '@humanwhocodes/config-array': 0.11.14
+ '@eslint/config-array': 0.15.1
+ '@eslint/eslintrc': 3.1.0
+ '@eslint/js': 9.4.0
'@humanwhocodes/module-importer': 1.0.1
+ '@humanwhocodes/retry': 0.3.0
'@nodelib/fs.walk': 1.2.8
- '@ungap/structured-clone': 1.2.0
ajv: 6.12.6
chalk: 4.1.2
cross-spawn: 7.0.3
debug: 4.3.4
- doctrine: 3.0.0
escape-string-regexp: 4.0.0
- eslint-scope: 7.2.2
- eslint-visitor-keys: 3.4.3
- espree: 9.6.1
+ eslint-scope: 8.0.1
+ eslint-visitor-keys: 4.0.0
+ espree: 10.0.1
esquery: 1.5.0
esutils: 2.0.3
fast-deep-equal: 3.1.3
- file-entry-cache: 6.0.1
+ file-entry-cache: 8.0.0
find-up: 5.0.0
glob-parent: 6.0.2
- globals: 13.24.0
- graphemer: 1.4.0
ignore: 5.3.1
imurmurhash: 0.1.4
is-glob: 4.0.3
is-path-inside: 3.0.3
- js-yaml: 4.1.0
json-stable-stringify-without-jsonify: 1.0.1
levn: 0.4.1
lodash.merge: 4.6.2
@@ -9043,11 +9039,11 @@ snapshots:
transitivePeerDependencies:
- supports-color
- espree@9.6.1:
+ espree@10.0.1:
dependencies:
acorn: 8.11.3
acorn-jsx: 5.3.2(acorn@8.11.3)
- eslint-visitor-keys: 3.4.3
+ eslint-visitor-keys: 4.0.0
esprima@4.0.1: {}
@@ -9129,9 +9125,9 @@ snapshots:
dependencies:
escape-string-regexp: 1.0.5
- file-entry-cache@6.0.1:
+ file-entry-cache@8.0.0:
dependencies:
- flat-cache: 3.2.0
+ flat-cache: 4.0.1
file-uri-to-path@1.0.0: {}
@@ -9146,11 +9142,10 @@ snapshots:
flag-icons@7.2.3: {}
- flat-cache@3.2.0:
+ flat-cache@4.0.1:
dependencies:
flatted: 3.2.9
keyv: 4.5.4
- rimraf: 3.0.2
flatted@3.2.9: {}
@@ -9304,9 +9299,7 @@ snapshots:
globals@11.12.0: {}
- globals@13.24.0:
- dependencies:
- type-fest: 0.20.2
+ globals@14.0.0: {}
globalthis@1.0.3:
dependencies:
@@ -11338,8 +11331,6 @@ snapshots:
type-detect@4.0.8: {}
- type-fest@0.20.2: {}
-
type-fest@0.21.3: {}
type-fest@2.19.0: {}
@@ -11405,6 +11396,17 @@ snapshots:
is-typed-array: 1.1.13
possible-typed-array-names: 1.0.0
+ typescript-eslint@7.12.0(eslint@9.4.0)(typescript@5.4.5):
+ dependencies:
+ '@typescript-eslint/eslint-plugin': 7.12.0(@typescript-eslint/parser@7.12.0(eslint@9.4.0)(typescript@5.4.5))(eslint@9.4.0)(typescript@5.4.5)
+ '@typescript-eslint/parser': 7.12.0(eslint@9.4.0)(typescript@5.4.5)
+ '@typescript-eslint/utils': 7.12.0(eslint@9.4.0)(typescript@5.4.5)
+ eslint: 9.4.0
+ optionalDependencies:
+ typescript: 5.4.5
+ transitivePeerDependencies:
+ - supports-color
+
typescript@5.4.5: {}
uc.micro@2.1.0: {}
diff --git a/tooling/eslint/base.js b/tooling/eslint/base.js
index bb154044f..118762731 100644
--- a/tooling/eslint/base.js
+++ b/tooling/eslint/base.js
@@ -1,80 +1,90 @@
-/** @type {import("eslint").Linter.Config} */
-const config = {
- extends: [
- "turbo",
- "eslint:recommended",
- "plugin:@typescript-eslint/recommended-type-checked",
- "plugin:@typescript-eslint/stylistic-type-checked",
- "prettier",
- ],
- env: {
- es2022: true,
- node: true,
- },
- parser: "@typescript-eslint/parser",
- parserOptions: {
- project: true,
- },
- plugins: ["@typescript-eslint", "import"],
- rules: {
- "id-length": [
- "warn",
- {
- min: 3,
- exceptions: ["_", "i", "z", "t", "id", "db"], // _ for unused variables, i for index, z for zod, t for translation
- properties: "never", // This allows for example the use of as sm and md would be too short
- },
- ],
- "@typescript-eslint/prefer-nullish-coalescing": "off",
- "turbo/no-undeclared-env-vars": "off",
- "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }],
- "@typescript-eslint/consistent-type-imports": [
- "warn",
- { prefer: "type-imports", fixStyle: "separate-type-imports" },
- ],
- "@typescript-eslint/no-misused-promises": [2, { checksVoidReturn: { attributes: false } }],
- "import/consistent-type-specifier-style": ["error", "prefer-top-level"],
- "no-restricted-syntax": [
- "error",
- {
- selector: "FunctionDeclaration[async=false][id.name=/Async$/]",
- message: "Function ending in 'Async' must be declared async",
- },
- {
- selector:
- "FunctionDeclaration[async=true][id.name=/^[a-z].*$/][id.name=/ ^(?!generateMetadata$)[a-z].*$/][id.name!=/Async$/]",
- message: "Async function name must end in 'Async' (function declaration)",
- },
- {
- selector: "MethodDefinition[value.async=false][key.name=/Async$/]",
- message: "Method ending in 'Async' must be declared async",
- },
- {
- selector: "MethodDefinition[value.async=true][key.name!=/Async$/]",
- message: "Async method name must end in 'Async'",
- },
- {
- selector: "Property[value.type=/FunctionExpression$/][value.async=false][key.name=/Async$/]",
- message: "Function ending in 'Async' must be declared async",
- },
- {
- selector:
- "Property[value.type=/FunctionExpression$/][value.async=true][key.name!=/^on(Success|Settled)$/][key.name!=/Async$/]",
- message: "Async function name must end in 'Async' (property)",
- },
- {
- selector: "VariableDeclarator[init.type=/FunctionExpression$/][init.async=false][id.name=/Async$/]",
- message: "Function ending in 'Async' must be declared async",
- },
- {
- selector:
- "VariableDeclarator[init.type=/FunctionExpression$/][init.async=true][id.name=/^[a-z].*$/][id.name!=/Async$/]",
- message: "Async function name must end in 'Async' (variable declarator)",
- },
- ],
- },
- ignorePatterns: ["**/.eslintrc.cjs", "**/*.config.js", "**/*.config.cjs", ".next", "dist", "pnpm-lock.yaml"],
- reportUnusedDisableDirectives: true,
-};
+///
-module.exports = config;
+import eslint from "@eslint/js";
+import importPlugin from "eslint-plugin-import";
+import tseslint from "typescript-eslint";
+
+export default tseslint.config(
+ {
+ // Globally ignored files
+ ignores: ["**/*.config.js"],
+ },
+ {
+ files: ["**/*.js", "**/*.ts", "**/*.tsx"],
+ plugins: {
+ import: importPlugin,
+ },
+ extends: [
+ eslint.configs.recommended,
+ ...tseslint.configs.recommended,
+ ...tseslint.configs.recommendedTypeChecked,
+ ...tseslint.configs.stylisticTypeChecked,
+ ],
+ rules: {
+ "@typescript-eslint/no-unused-vars": ["error", { argsIgnorePattern: "^_", varsIgnorePattern: "^_" }],
+ "@typescript-eslint/consistent-type-imports": [
+ "warn",
+ { prefer: "type-imports", fixStyle: "separate-type-imports" },
+ ],
+ "@typescript-eslint/no-misused-promises": [2, { checksVoidReturn: { attributes: false } }],
+ "@typescript-eslint/no-unnecessary-condition": [
+ "error",
+ {
+ allowConstantLoopConditions: true,
+ },
+ ],
+ "@typescript-eslint/no-non-null-assertion": "error",
+ "import/consistent-type-specifier-style": ["error", "prefer-top-level"],
+ "id-length": [
+ "warn",
+ {
+ min: 3,
+ exceptions: ["_", "i", "z", "t", "id", "db"], // _ for unused variables, i for index, z for zod, t for translation
+ properties: "never", // This allows for example the use of as sm and md would be too short
+ },
+ ],
+ "no-restricted-syntax": [
+ "error",
+ {
+ selector: "FunctionDeclaration[async=false][id.name=/Async$/]",
+ message: "Function ending in 'Async' must be declared async",
+ },
+ {
+ selector:
+ "FunctionDeclaration[async=true][id.name=/^[a-z].*$/][id.name=/ ^(?!generateMetadata$)[a-z].*$/][id.name!=/Async$/]",
+ message: "Async function name must end in 'Async' (function declaration)",
+ },
+ {
+ selector: "MethodDefinition[value.async=false][key.name=/Async$/]",
+ message: "Method ending in 'Async' must be declared async",
+ },
+ {
+ selector: "MethodDefinition[value.async=true][key.name!=/Async$/]",
+ message: "Async method name must end in 'Async'",
+ },
+ {
+ selector: "Property[value.type=/FunctionExpression$/][value.async=false][key.name=/Async$/]",
+ message: "Function ending in 'Async' must be declared async",
+ },
+ {
+ selector:
+ "Property[value.type=/FunctionExpression$/][value.async=true][key.name!=/^on(Success|Settled)$/][key.name!=/Async$/]",
+ message: "Async function name must end in 'Async' (property)",
+ },
+ {
+ selector: "VariableDeclarator[init.type=/FunctionExpression$/][init.async=false][id.name=/Async$/]",
+ message: "Function ending in 'Async' must be declared async",
+ },
+ {
+ selector:
+ "VariableDeclarator[init.type=/FunctionExpression$/][init.async=true][id.name=/^[a-z].*$/][id.name!=/Async$/]",
+ message: "Async function name must end in 'Async' (variable declarator)",
+ },
+ ],
+ },
+ },
+ {
+ linterOptions: { reportUnusedDisableDirectives: true },
+ languageOptions: { parserOptions: { project: true } },
+ },
+);
diff --git a/tooling/eslint/eslint.config.js b/tooling/eslint/eslint.config.js
new file mode 100644
index 000000000..f7a5a7d36
--- /dev/null
+++ b/tooling/eslint/eslint.config.js
@@ -0,0 +1,4 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [...baseConfig];
diff --git a/tooling/eslint/nextjs.js b/tooling/eslint/nextjs.js
index 278d86600..b876fc84e 100644
--- a/tooling/eslint/nextjs.js
+++ b/tooling/eslint/nextjs.js
@@ -1,9 +1,17 @@
-/** @type {import('eslint').Linter.Config} */
-const config = {
- extends: ["plugin:@next/next/recommended"],
- rules: {
- "@next/next/no-html-link-for-pages": "off",
- },
-};
+import nextPlugin from "@next/eslint-plugin-next";
-module.exports = config;
+/** @type {Awaited} */
+export default [
+ {
+ files: ["**/*.ts", "**/*.tsx"],
+ plugins: {
+ "@next/next": nextPlugin,
+ },
+ rules: {
+ ...nextPlugin.configs.recommended.rules,
+ ...nextPlugin.configs["core-web-vitals"].rules,
+ // TypeError: context.getAncestors is not a function
+ "@next/next/no-duplicate-head": "off",
+ },
+ },
+];
diff --git a/tooling/eslint/package.json b/tooling/eslint/package.json
index 842227482..18f52c7ec 100644
--- a/tooling/eslint/package.json
+++ b/tooling/eslint/package.json
@@ -3,40 +3,33 @@
"version": "0.2.0",
"private": true,
"license": "MIT",
- "files": [
- "./base.js",
- "./nextjs.js",
- "./react.js"
- ],
+ "type": "module",
+ "exports": {
+ "./base": "./base.js",
+ "./nextjs": "./nextjs.js",
+ "./react": "./react.js"
+ },
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@next/eslint-plugin-next": "^14.2.3",
- "@typescript-eslint/eslint-plugin": "^7.12.0",
- "@typescript-eslint/parser": "^7.12.0",
"eslint-config-prettier": "^9.1.0",
"eslint-config-turbo": "^2.0.3",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jsx-a11y": "^6.8.0",
"eslint-plugin-react": "^7.34.2",
- "eslint-plugin-react-hooks": "^4.6.2"
+ "eslint-plugin-react-hooks": "^4.6.2",
+ "typescript-eslint": "^7.12.0"
},
"devDependencies": {
- "@types/eslint": "^8.56.10",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "root": true,
- "extends": [
- "./base.js"
- ]
- },
"prettier": "@homarr/prettier-config"
}
diff --git a/tooling/eslint/react.js b/tooling/eslint/react.js
index ee21a219f..a87b5c165 100644
--- a/tooling/eslint/react.js
+++ b/tooling/eslint/react.js
@@ -1,20 +1,24 @@
-/** @type {import('eslint').Linter.Config} */
-const config = {
- extends: ["plugin:react/recommended", "plugin:react-hooks/recommended", "plugin:jsx-a11y/recommended"],
- rules: {
- "react/prop-types": "off",
- },
- globals: {
- React: "writable",
- },
- settings: {
- react: {
- version: "detect",
+import reactPlugin from "eslint-plugin-react";
+import hooksPlugin from "eslint-plugin-react-hooks";
+
+/** @type {Awaited} */
+export default [
+ {
+ files: ["**/*.ts", "**/*.tsx"],
+ plugins: {
+ react: reactPlugin,
+ "react-hooks": hooksPlugin,
+ },
+ rules: {
+ ...reactPlugin.configs["jsx-runtime"].rules,
+ ...hooksPlugin.configs.recommended.rules,
+ // context.getSource is not a function
+ "react-hooks/exhaustive-deps": "off",
+ },
+ languageOptions: {
+ globals: {
+ React: "writable",
+ },
},
},
- env: {
- browser: true,
- },
-};
-
-module.exports = config;
+];
diff --git a/tooling/eslint/types.d.ts b/tooling/eslint/types.d.ts
new file mode 100644
index 000000000..37cfded93
--- /dev/null
+++ b/tooling/eslint/types.d.ts
@@ -0,0 +1,58 @@
+/**
+ * Since the ecosystem hasn't fully migrated to ESLint's new FlatConfig system yet,
+ * we "need" to type some of the plugins manually :(
+ */
+
+declare module "@eslint/js" {
+ // Why the hell doesn't eslint themselves export their types?
+ import type { Linter } from "eslint";
+
+ export const configs: {
+ readonly recommended: { readonly rules: Readonly };
+ readonly all: { readonly rules: Readonly };
+ };
+}
+
+declare module "eslint-plugin-import" {
+ import type { Linter, Rule } from "eslint";
+
+ export const configs: {
+ recommended: { rules: Linter.RulesRecord };
+ };
+ export const rules: Record;
+}
+
+declare module "eslint-plugin-react" {
+ import type { Linter, Rule } from "eslint";
+
+ export const configs: {
+ recommended: { rules: Linter.RulesRecord };
+ all: { rules: Linter.RulesRecord };
+ "jsx-runtime": { rules: Linter.RulesRecord };
+ };
+ export const rules: Record;
+}
+
+declare module "eslint-plugin-react-hooks" {
+ import type { Linter, Rule } from "eslint";
+
+ export const configs: {
+ recommended: {
+ rules: {
+ "rules-of-hooks": Linter.RuleEntry;
+ "exhaustive-deps": Linter.RuleEntry;
+ };
+ };
+ };
+ export const rules: Record;
+}
+
+declare module "@next/eslint-plugin-next" {
+ import type { Linter, Rule } from "eslint";
+
+ export const configs: {
+ recommended: { rules: Linter.RulesRecord };
+ "core-web-vitals": { rules: Linter.RulesRecord };
+ };
+ export const rules: Record;
+}
diff --git a/tooling/typescript/base.json b/tooling/typescript/base.json
index 944bb0a3c..37f6290fb 100644
--- a/tooling/typescript/base.json
+++ b/tooling/typescript/base.json
@@ -2,7 +2,11 @@
"$schema": "https://json.schemastore.org/tsconfig",
"compilerOptions": {
"target": "ES2022",
- "lib": ["dom", "dom.iterable", "ES2022"],
+ "lib": [
+ "dom",
+ "dom.iterable",
+ "ES2022"
+ ],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
@@ -16,6 +20,7 @@
"jsx": "preserve",
"incremental": true,
"noUncheckedIndexedAccess": true,
+ "strictNullChecks": true,
"baseUrl": ".",
"paths": {
"*": [
@@ -23,5 +28,10 @@
]
}
},
- "exclude": ["node_modules", "build", "dist", ".next"]
-}
+ "exclude": [
+ "node_modules",
+ "build",
+ "dist",
+ ".next"
+ ]
+}
\ No newline at end of file
diff --git a/turbo/generators/config.ts b/turbo/generators/config.ts
index 1bf6d4896..4ee93a8f8 100644
--- a/turbo/generators/config.ts
+++ b/turbo/generators/config.ts
@@ -15,14 +15,12 @@ export default function generator(plop: PlopTypes.NodePlopAPI): void {
{
type: "input",
name: "name",
- message:
- "What is the name of the package? (You can skip the `@homarr/` prefix)",
+ message: "What is the name of the package? (You can skip the `@homarr/` prefix)",
},
{
type: "input",
name: "deps",
- message:
- "Enter a space separated list of dependencies you would like to install",
+ message: "Enter a space separated list of dependencies you would like to install",
},
],
actions: [
@@ -34,6 +32,11 @@ export default function generator(plop: PlopTypes.NodePlopAPI): void {
}
return "Config sanitized";
},
+ {
+ type: "add",
+ path: "packages/{{ name }}/eslint.config.js",
+ templateFile: "templates/eslint.config.js.hbs",
+ },
{
type: "add",
path: "packages/{{ name }}/package.json",
@@ -61,9 +64,7 @@ export default function generator(plop: PlopTypes.NodePlopAPI): void {
if ("deps" in answers && typeof answers.deps === "string") {
const pkg = JSON.parse(content) as PackageJson;
for (const dep of answers.deps.split(" ").filter(Boolean)) {
- const version = await fetch(
- `https://registry.npmjs.org/-/package/${dep}/dist-tags`,
- )
+ const version = await fetch(`https://registry.npmjs.org/-/package/${dep}/dist-tags`)
.then((res) => res.json())
.then((json) => json.latest);
if (!pkg.dependencies) pkg.dependencies = {};
@@ -83,9 +84,7 @@ export default function generator(plop: PlopTypes.NodePlopAPI): void {
// stdio: "inherit",
// });
execSync("pnpm i", { stdio: "inherit" });
- execSync(
- `pnpm prettier --write packages/${answers.name}/** --list-different`,
- );
+ execSync(`pnpm prettier --write packages/${answers.name}/** --list-different`);
return "Package scaffolded";
}
return "Package not scaffolded";
diff --git a/turbo/generators/templates/eslint.config.js.hbs b/turbo/generators/templates/eslint.config.js.hbs
new file mode 100644
index 000000000..26c6c4ba1
--- /dev/null
+++ b/turbo/generators/templates/eslint.config.js.hbs
@@ -0,0 +1,9 @@
+import baseConfig from "@homarr/eslint-config/base";
+
+/** @type {import('typescript-eslint').Config} */
+export default [
+ {
+ ignores: [],
+ },
+ ...baseConfig,
+];
\ No newline at end of file
diff --git a/turbo/generators/templates/package.json.hbs b/turbo/generators/templates/package.json.hbs
index fd1754a76..90ca0774f 100644
--- a/turbo/generators/templates/package.json.hbs
+++ b/turbo/generators/templates/package.json.hbs
@@ -2,6 +2,7 @@
"name": "@homarr/{{name}}",
"private": true,
"version": "0.1.0",
+ "type": "module",
"exports": {
".": "./index.ts"
},
@@ -15,7 +16,7 @@
"license": "MIT",
"scripts": {
"clean": "rm -rf .turbo node_modules",
- "lint": "eslint .",
+ "lint": "eslint",
"format": "prettier --check . --ignore-path ../../.gitignore",
"typecheck": "tsc --noEmit"
},
@@ -23,13 +24,8 @@
"@homarr/eslint-config": "workspace:^0.2.0",
"@homarr/prettier-config": "workspace:^0.1.0",
"@homarr/tsconfig": "workspace:^0.1.0",
- "eslint": "^8.57.0",
+ "eslint": "^9.4.0",
"typescript": "^5.4.5"
},
- "eslintConfig": {
- "extends": [
- "@homarr/eslint-config/base"
- ]
- },
"prettier": "@homarr/prettier-config"
}
\ No newline at end of file