mirror of
https://github.com/ajnart/homarr.git
synced 2026-02-27 00:40:58 +01:00
chore(release): automatic release v1.0.0
This commit is contained in:
10
.github/workflows/deployment-docker-image.yml
vendored
10
.github/workflows/deployment-docker-image.yml
vendored
@@ -40,6 +40,7 @@ jobs:
|
||||
SKIP_RELEASE: ${{ github.event_name == 'workflow_dispatch' || github.ref_name == 'dev' }}
|
||||
outputs:
|
||||
version: ${{ steps.read-semver.outputs.version || steps.version-fallback.outputs.version }}
|
||||
git_ref: ${{ steps.read-git-ref.outputs.ref || github.ref }}
|
||||
|
||||
steps:
|
||||
- run: echo "Skipping release for workflow_dispatch event"
|
||||
@@ -87,9 +88,16 @@ jobs:
|
||||
run: |
|
||||
git fetch --tags
|
||||
echo "version=$(git describe --tags --abbrev=0)" >> "$GITHUB_OUTPUT"
|
||||
- name: Read git ref
|
||||
if: env.SKIP_RELEASE == 'false'
|
||||
id: read-git-ref
|
||||
run: |
|
||||
echo "ref=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
||||
- name: Update dev branch
|
||||
if: env.SKIP_RELEASE == 'false'
|
||||
continue-on-error: true # Prevent pipeline from failing when merge fails
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ steps.obtainToken.outputs.token }}
|
||||
run: |
|
||||
git fetch origin dev
|
||||
git checkout dev
|
||||
@@ -107,6 +115,8 @@ jobs:
|
||||
PUSH_IMAGE: ${{ github.event_name != 'workflow_dispatch' || github.events.inputs.push-image == true }}
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ needs.release.outputs.git_ref }}
|
||||
- name: Discord notification
|
||||
if: ${{ github.events.inputs.send-notifications != false }}
|
||||
env:
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Importing env files here to validate on build
|
||||
import "@homarr/auth/env.mjs";
|
||||
import "@homarr/db/env.mjs";
|
||||
|
||||
import MillionLint from "@million/lint";
|
||||
import createNextIntlPlugin from "next-intl/plugin";
|
||||
|
||||
@@ -65,7 +65,7 @@
|
||||
"glob": "^11.0.0",
|
||||
"jotai": "^2.10.4",
|
||||
"mantine-react-table": "2.0.0-beta.7",
|
||||
"next": "^14.2.20",
|
||||
"next": "^14.2.21",
|
||||
"postcss-preset-mantine": "^1.17.0",
|
||||
"prismjs": "^1.29.0",
|
||||
"react": "^19.0.0",
|
||||
@@ -84,7 +84,7 @@
|
||||
"@types/chroma-js": "2.4.5",
|
||||
"@types/node": "^22.10.2",
|
||||
"@types/prismjs": "^1.26.5",
|
||||
"@types/react": "^19.0.1",
|
||||
"@types/react": "^19.0.2",
|
||||
"@types/react-dom": "^19.0.2",
|
||||
"@types/swagger-ui-react": "^4.18.3",
|
||||
"concurrently": "^9.1.0",
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Card, Center, Stack, Text, Title } from "@mantine/core";
|
||||
import { auth } from "@homarr/auth/next";
|
||||
import { isProviderEnabled } from "@homarr/auth/server";
|
||||
import { and, db, eq } from "@homarr/db";
|
||||
import { invites } from "@homarr/db/schema/sqlite";
|
||||
import { invites } from "@homarr/db/schema";
|
||||
import { getScopedI18n } from "@homarr/translation/server";
|
||||
|
||||
import { HomarrLogoWithTitle } from "~/components/layout/logo/homarr-logo";
|
||||
|
||||
@@ -2,7 +2,7 @@ import { IconHomeOff } from "@tabler/icons-react";
|
||||
|
||||
import { auth } from "@homarr/auth/next";
|
||||
import { db } from "@homarr/db";
|
||||
import { boards } from "@homarr/db/schema/sqlite";
|
||||
import { boards } from "@homarr/db/schema";
|
||||
import { getI18n } from "@homarr/translation/server";
|
||||
|
||||
import type { BoardNotFoundProps } from "~/components/board/not-found";
|
||||
|
||||
@@ -24,10 +24,19 @@ export const ImportDropZone = ({ loading, updateFile }: ImportDropZoneProps) =>
|
||||
}}
|
||||
acceptColor="blue.6"
|
||||
rejectColor="red.6"
|
||||
accept={[MIME_TYPES.zip]}
|
||||
accept={[MIME_TYPES.zip, "application/x-zip-compressed"]}
|
||||
loading={loading}
|
||||
multiple={false}
|
||||
maxSize={1024 * 1024 * 1024 * 64} // 64 MB
|
||||
onReject={(rejections) => {
|
||||
console.error(
|
||||
"Rejected files",
|
||||
rejections.map(
|
||||
(rejection) =>
|
||||
`File: ${rejection.file.name} size=${rejection.file.size} fileType=${rejection.file.type}\n - ${rejection.errors.map((error) => error.message).join("\n - ")}`,
|
||||
),
|
||||
);
|
||||
}}
|
||||
>
|
||||
<Group justify="center" gap="xl" mih={220} style={{ pointerEvents: "none" }}>
|
||||
<Dropzone.Accept>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { notFound } from "next/navigation";
|
||||
import { auth } from "@homarr/auth/next";
|
||||
import { isProviderEnabled } from "@homarr/auth/server";
|
||||
import { db, inArray } from "@homarr/db";
|
||||
import { groups } from "@homarr/db/schema/sqlite";
|
||||
import { groups } from "@homarr/db/schema";
|
||||
import { everyoneGroup } from "@homarr/definitions";
|
||||
import { getScopedI18n } from "@homarr/translation/server";
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ import { hashPasswordAsync } from "@homarr/auth";
|
||||
import type { Session } from "@homarr/auth";
|
||||
import { createSessionAsync } from "@homarr/auth/server";
|
||||
import { db, eq } from "@homarr/db";
|
||||
import { apiKeys } from "@homarr/db/schema/sqlite";
|
||||
import { apiKeys } from "@homarr/db/schema";
|
||||
import { logger } from "@homarr/log";
|
||||
|
||||
const handlerAsync = async (req: NextRequest) => {
|
||||
|
||||
@@ -3,7 +3,7 @@ import { NextResponse } from "next/server";
|
||||
import type { NextRequest } from "next/server";
|
||||
|
||||
import { db, eq } from "@homarr/db";
|
||||
import { medias } from "@homarr/db/schema/sqlite";
|
||||
import { medias } from "@homarr/db/schema";
|
||||
|
||||
export async function GET(_req: NextRequest, { params }: { params: { id: string } }) {
|
||||
const image = await db.query.medias.findFirst({
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import { createEnv } from "@t3-oss/env-nextjs";
|
||||
import { z } from "zod";
|
||||
|
||||
const isUsingDbUrl = Boolean(process.env.DB_URL);
|
||||
const isUsingDbHost = Boolean(process.env.DB_HOST);
|
||||
const isUsingDbCredentials = process.env.DB_DRIVER === "mysql2";
|
||||
|
||||
export const env = createEnv({
|
||||
shared: {
|
||||
VERCEL_URL: z
|
||||
@@ -19,21 +15,6 @@ export const env = createEnv({
|
||||
* built with invalid env vars.
|
||||
*/
|
||||
server: {
|
||||
DB_DRIVER: z.enum(["better-sqlite3", "mysql2"]).default("better-sqlite3"),
|
||||
// If the DB_HOST is set, the DB_URL is optional
|
||||
DB_URL: isUsingDbHost ? z.string().optional() : z.string(),
|
||||
DB_HOST: isUsingDbUrl ? z.string().optional() : z.string(),
|
||||
DB_PORT: isUsingDbUrl
|
||||
? z.string().regex(/\d+/).transform(Number).optional()
|
||||
: z
|
||||
.string()
|
||||
.regex(/\d+/)
|
||||
.transform(Number)
|
||||
.refine((number) => number >= 1)
|
||||
.default("3306"),
|
||||
DB_USER: isUsingDbCredentials ? z.string() : z.string().optional(),
|
||||
DB_PASSWORD: isUsingDbCredentials ? z.string() : z.string().optional(),
|
||||
DB_NAME: isUsingDbUrl ? z.string().optional() : z.string(),
|
||||
// Comma separated list of docker hostnames that can be used to connect to query the docker endpoints (localhost:2375,host.docker.internal:2375, ...)
|
||||
DOCKER_HOSTNAMES: z.string().optional(),
|
||||
DOCKER_PORTS: z.number().optional(),
|
||||
@@ -51,13 +32,6 @@ export const env = createEnv({
|
||||
runtimeEnv: {
|
||||
VERCEL_URL: process.env.VERCEL_URL,
|
||||
PORT: process.env.PORT,
|
||||
DB_URL: process.env.DB_URL,
|
||||
DB_HOST: process.env.DB_HOST,
|
||||
DB_USER: process.env.DB_USER,
|
||||
DB_PASSWORD: process.env.DB_PASSWORD,
|
||||
DB_NAME: process.env.DB_NAME,
|
||||
DB_PORT: process.env.DB_PORT,
|
||||
DB_DRIVER: process.env.DB_DRIVER,
|
||||
NODE_ENV: process.env.NODE_ENV,
|
||||
DOCKER_HOSTNAMES: process.env.DOCKER_HOSTNAMES,
|
||||
DOCKER_PORTS: process.env.DOCKER_PORTS,
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
"dayjs": "^1.11.13",
|
||||
"dotenv": "^16.4.7",
|
||||
"superjson": "2.2.2",
|
||||
"undici": "7.1.1"
|
||||
"undici": "7.2.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Umami } from "@umami/node";
|
||||
|
||||
import { count, db } from "@homarr/db";
|
||||
import { getServerSettingByKeyAsync } from "@homarr/db/queries";
|
||||
import { integrations, items, users } from "@homarr/db/schema/sqlite";
|
||||
import { integrations, items, users } from "@homarr/db/schema";
|
||||
import { logger } from "@homarr/log";
|
||||
import type { defaultServerSettings } from "@homarr/server-settings";
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
"@trpc/react-query": "next",
|
||||
"@trpc/server": "next",
|
||||
"dockerode": "^4.0.2",
|
||||
"next": "^14.2.20",
|
||||
"next": "^14.2.21",
|
||||
"react": "^19.0.0",
|
||||
"superjson": "2.2.2",
|
||||
"trpc-to-openapi": "^2.1.0"
|
||||
|
||||
@@ -7,7 +7,7 @@ import { decryptSecret } from "@homarr/common/server";
|
||||
import type { AtLeastOneOf } from "@homarr/common/types";
|
||||
import type { Database } from "@homarr/db";
|
||||
import { and, eq, inArray } from "@homarr/db";
|
||||
import { integrations } from "@homarr/db/schema/sqlite";
|
||||
import { integrations } from "@homarr/db/schema";
|
||||
import type { IntegrationKind } from "@homarr/definitions";
|
||||
import { z } from "@homarr/validation";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
import { and, eq } from "@homarr/db";
|
||||
import { items } from "@homarr/db/schema/sqlite";
|
||||
import { items } from "@homarr/db/schema";
|
||||
import type { WidgetKind } from "@homarr/definitions";
|
||||
import { z } from "@homarr/validation";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { createSaltAsync, hashPasswordAsync } from "@homarr/auth";
|
||||
import { generateSecureRandomToken } from "@homarr/common/server";
|
||||
import { createId, db } from "@homarr/db";
|
||||
import { apiKeys } from "@homarr/db/schema/sqlite";
|
||||
import { apiKeys } from "@homarr/db/schema";
|
||||
|
||||
import { createTRPCRouter, permissionRequiredProcedure } from "../trpc";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
import { asc, createId, eq, inArray, like } from "@homarr/db";
|
||||
import { apps } from "@homarr/db/schema/sqlite";
|
||||
import { apps } from "@homarr/db/schema";
|
||||
import { selectAppSchema } from "@homarr/db/validationSchemas";
|
||||
import { validation, z } from "@homarr/validation";
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import SuperJSON from "superjson";
|
||||
|
||||
import type { Session } from "@homarr/auth";
|
||||
import { db, eq, or } from "@homarr/db";
|
||||
import { items } from "@homarr/db/schema/sqlite";
|
||||
import { items } from "@homarr/db/schema";
|
||||
|
||||
import type { WidgetComponentProps } from "../../../../widgets/src";
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ import {
|
||||
items,
|
||||
sections,
|
||||
users,
|
||||
} from "@homarr/db/schema/sqlite";
|
||||
} from "@homarr/db/schema";
|
||||
import type { WidgetKind } from "@homarr/definitions";
|
||||
import { getPermissionsWithParents, widgetKinds } from "@homarr/definitions";
|
||||
import { importOldmarrAsync } from "@homarr/old-import";
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { Session } from "@homarr/auth";
|
||||
import { constructBoardPermissions } from "@homarr/auth/shared";
|
||||
import type { Database, SQL } from "@homarr/db";
|
||||
import { eq, inArray } from "@homarr/db";
|
||||
import { boardGroupPermissions, boardUserPermissions, groupMembers } from "@homarr/db/schema/sqlite";
|
||||
import { boardGroupPermissions, boardUserPermissions, groupMembers } from "@homarr/db/schema";
|
||||
import type { BoardPermission } from "@homarr/definitions";
|
||||
|
||||
/**
|
||||
|
||||
@@ -3,7 +3,7 @@ import type Docker from "dockerode";
|
||||
import type { Container } from "dockerode";
|
||||
|
||||
import { db, like, or } from "@homarr/db";
|
||||
import { icons } from "@homarr/db/schema/sqlite";
|
||||
import { icons } from "@homarr/db/schema";
|
||||
import type { DockerContainerState } from "@homarr/definitions";
|
||||
import { logger } from "@homarr/log";
|
||||
import { createCacheChannel } from "@homarr/redis";
|
||||
|
||||
@@ -2,7 +2,7 @@ import { TRPCError } from "@trpc/server";
|
||||
|
||||
import type { Database } from "@homarr/db";
|
||||
import { and, createId, eq, like, not, sql } from "@homarr/db";
|
||||
import { groupMembers, groupPermissions, groups } from "@homarr/db/schema/sqlite";
|
||||
import { groupMembers, groupPermissions, groups } from "@homarr/db/schema";
|
||||
import { everyoneGroup } from "@homarr/definitions";
|
||||
import { validation, z } from "@homarr/validation";
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { AnySQLiteTable } from "drizzle-orm/sqlite-core";
|
||||
import { isProviderEnabled } from "@homarr/auth/server";
|
||||
import type { Database } from "@homarr/db";
|
||||
import { count } from "@homarr/db";
|
||||
import { apps, boards, groups, integrations, invites, users } from "@homarr/db/schema/sqlite";
|
||||
import { apps, boards, groups, integrations, invites, users } from "@homarr/db/schema";
|
||||
|
||||
import { createTRPCRouter, publicProcedure } from "../trpc";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { count, like } from "@homarr/db";
|
||||
import { icons } from "@homarr/db/schema/sqlite";
|
||||
import { icons } from "@homarr/db/schema";
|
||||
import { validation } from "@homarr/validation";
|
||||
|
||||
import { createTRPCRouter, publicProcedure } from "../trpc";
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { Session } from "@homarr/auth";
|
||||
import { constructIntegrationPermissions } from "@homarr/auth/shared";
|
||||
import type { Database, SQL } from "@homarr/db";
|
||||
import { eq, inArray } from "@homarr/db";
|
||||
import { groupMembers, integrationGroupPermissions, integrationUserPermissions } from "@homarr/db/schema/sqlite";
|
||||
import { groupMembers, integrationGroupPermissions, integrationUserPermissions } from "@homarr/db/schema";
|
||||
import type { IntegrationPermission } from "@homarr/definitions";
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
integrations,
|
||||
integrationSecrets,
|
||||
integrationUserPermissions,
|
||||
} from "@homarr/db/schema/sqlite";
|
||||
} from "@homarr/db/schema";
|
||||
import type { IntegrationSecretKind } from "@homarr/definitions";
|
||||
import {
|
||||
getIntegrationKindsByCategory,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { decryptSecret } from "@homarr/common/server";
|
||||
import type { Integration } from "@homarr/db/schema/sqlite";
|
||||
import type { Integration } from "@homarr/db/schema";
|
||||
import type { IntegrationKind, IntegrationSecretKind } from "@homarr/definitions";
|
||||
import { getAllSecretKindOptions } from "@homarr/definitions";
|
||||
import { integrationCreator, IntegrationTestConnectionError } from "@homarr/integrations";
|
||||
|
||||
@@ -2,7 +2,7 @@ import { randomBytes } from "crypto";
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
import { asc, createId, eq } from "@homarr/db";
|
||||
import { invites } from "@homarr/db/schema/sqlite";
|
||||
import { invites } from "@homarr/db/schema";
|
||||
import { selectInviteSchema } from "@homarr/db/validationSchemas";
|
||||
import { z } from "@homarr/validation";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
import { and, createId, desc, eq, like } from "@homarr/db";
|
||||
import { medias } from "@homarr/db/schema/sqlite";
|
||||
import { medias } from "@homarr/db/schema";
|
||||
import { validation, z } from "@homarr/validation";
|
||||
|
||||
import { createTRPCRouter, permissionRequiredProcedure, protectedProcedure } from "../../trpc";
|
||||
|
||||
@@ -3,7 +3,7 @@ import { objectEntries } from "@homarr/common";
|
||||
import type { MaybePromise } from "@homarr/common/types";
|
||||
import type { Database } from "@homarr/db";
|
||||
import { eq } from "@homarr/db";
|
||||
import { groups, onboarding } from "@homarr/db/schema/sqlite";
|
||||
import { groups, onboarding } from "@homarr/db/schema";
|
||||
import type { OnboardingStep } from "@homarr/definitions";
|
||||
import { credentialsAdminGroup } from "@homarr/definitions";
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { onboarding } from "@homarr/db/schema/sqlite";
|
||||
import { onboarding } from "@homarr/db/schema";
|
||||
import { onboardingSteps } from "@homarr/definitions";
|
||||
import { z, zodEnumFromArray } from "@homarr/validation";
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { TRPCError } from "@trpc/server";
|
||||
|
||||
import { createId, eq, like, sql } from "@homarr/db";
|
||||
import { searchEngines } from "@homarr/db/schema/sqlite";
|
||||
import { searchEngines } from "@homarr/db/schema";
|
||||
import { validation } from "@homarr/validation";
|
||||
|
||||
import { createTRPCRouter, permissionRequiredProcedure, protectedProcedure } from "../../trpc";
|
||||
|
||||
@@ -3,7 +3,7 @@ import { describe, expect, test, vi } from "vitest";
|
||||
|
||||
import type { Session } from "@homarr/auth";
|
||||
import { createId } from "@homarr/db";
|
||||
import { apps } from "@homarr/db/schema/sqlite";
|
||||
import { apps } from "@homarr/db/schema";
|
||||
import { createDb } from "@homarr/db/test";
|
||||
import type { GroupPermissionKey } from "@homarr/definitions";
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ import {
|
||||
sections,
|
||||
serverSettings,
|
||||
users,
|
||||
} from "@homarr/db/schema/sqlite";
|
||||
} from "@homarr/db/schema";
|
||||
import { createDb } from "@homarr/db/test";
|
||||
import type { BoardPermission, GroupPermissionKey } from "@homarr/definitions";
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { describe, expect, test, vi } from "vitest";
|
||||
|
||||
import * as authShared from "@homarr/auth/shared";
|
||||
import { createId, eq } from "@homarr/db";
|
||||
import { boards, users } from "@homarr/db/schema/sqlite";
|
||||
import { boards, users } from "@homarr/db/schema";
|
||||
import { createDb } from "@homarr/db/test";
|
||||
|
||||
import { throwIfActionForbiddenAsync } from "../../board/board-access";
|
||||
|
||||
@@ -3,7 +3,7 @@ import { describe, expect, test, vi } from "vitest";
|
||||
import type { Session } from "@homarr/auth";
|
||||
import * as env from "@homarr/auth/env.mjs";
|
||||
import { createId, eq } from "@homarr/db";
|
||||
import { groupMembers, groupPermissions, groups, users } from "@homarr/db/schema/sqlite";
|
||||
import { groupMembers, groupPermissions, groups, users } from "@homarr/db/schema";
|
||||
import { createDb } from "@homarr/db/test";
|
||||
import type { GroupPermissionKey } from "@homarr/definitions";
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { describe, expect, test, vi } from "vitest";
|
||||
|
||||
import * as authShared from "@homarr/auth/shared";
|
||||
import { createId, eq } from "@homarr/db";
|
||||
import { integrations, users } from "@homarr/db/schema/sqlite";
|
||||
import { integrations, users } from "@homarr/db/schema";
|
||||
import { createDb } from "@homarr/db/test";
|
||||
|
||||
import { throwIfActionForbiddenAsync } from "../../integration/integration-access";
|
||||
|
||||
@@ -4,7 +4,7 @@ import { describe, expect, test, vi } from "vitest";
|
||||
import type { Session } from "@homarr/auth";
|
||||
import { encryptSecret } from "@homarr/common/server";
|
||||
import { createId } from "@homarr/db";
|
||||
import { integrations, integrationSecrets } from "@homarr/db/schema/sqlite";
|
||||
import { integrations, integrationSecrets } from "@homarr/db/schema";
|
||||
import { createDb } from "@homarr/db/test";
|
||||
import type { GroupPermissionKey } from "@homarr/definitions";
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { describe, expect, test, vi } from "vitest";
|
||||
|
||||
import type { Session } from "@homarr/auth";
|
||||
import { createId } from "@homarr/db";
|
||||
import { invites, users } from "@homarr/db/schema/sqlite";
|
||||
import { invites, users } from "@homarr/db/schema";
|
||||
import { createDb } from "@homarr/db/test";
|
||||
|
||||
import { inviteRouter } from "../invite";
|
||||
|
||||
@@ -3,7 +3,7 @@ import { describe, expect, test, vi } from "vitest";
|
||||
|
||||
import type { Session } from "@homarr/auth";
|
||||
import { createId } from "@homarr/db";
|
||||
import { serverSettings } from "@homarr/db/schema/sqlite";
|
||||
import { serverSettings } from "@homarr/db/schema";
|
||||
import { createDb } from "@homarr/db/test";
|
||||
import { defaultServerSettings, defaultServerSettingsKeys } from "@homarr/server-settings";
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@ import { describe, expect, it, test, vi } from "vitest";
|
||||
|
||||
import type { Session } from "@homarr/auth";
|
||||
import type { Database } from "@homarr/db";
|
||||
import { createId, eq, schema } from "@homarr/db";
|
||||
import { onboarding, users } from "@homarr/db/schema/sqlite";
|
||||
import { createId, eq } from "@homarr/db";
|
||||
import { invites, onboarding, users } from "@homarr/db/schema";
|
||||
import { createDb } from "@homarr/db/test";
|
||||
import type { GroupPermissionKey, OnboardingStep } from "@homarr/definitions";
|
||||
|
||||
@@ -121,7 +121,7 @@ describe("register should create a user with valid invitation", () => {
|
||||
await db.insert(users).values({
|
||||
id: userId,
|
||||
});
|
||||
await db.insert(schema.invites).values({
|
||||
await db.insert(invites).values({
|
||||
id: inviteId,
|
||||
token: inviteToken,
|
||||
creatorId: userId,
|
||||
@@ -176,7 +176,7 @@ describe("register should create a user with valid invitation", () => {
|
||||
await db.insert(users).values({
|
||||
id: userId,
|
||||
});
|
||||
await db.insert(schema.invites).values({
|
||||
await db.insert(invites).values({
|
||||
id: inviteId,
|
||||
token: inviteToken,
|
||||
creatorId: userId,
|
||||
@@ -211,7 +211,7 @@ describe("editProfile shoud update user", () => {
|
||||
|
||||
const emailVerified = new Date(2024, 0, 5);
|
||||
|
||||
await db.insert(schema.users).values({
|
||||
await db.insert(users).values({
|
||||
id: defaultOwnerId,
|
||||
name: "TEST 1",
|
||||
email: "abc@gmail.com",
|
||||
@@ -226,7 +226,7 @@ describe("editProfile shoud update user", () => {
|
||||
});
|
||||
|
||||
// assert
|
||||
const user = await db.select().from(schema.users).where(eq(schema.users.id, defaultOwnerId));
|
||||
const user = await db.select().from(users).where(eq(users.id, defaultOwnerId));
|
||||
|
||||
expect(user).toHaveLength(1);
|
||||
expect(user[0]).containSubset({
|
||||
@@ -245,7 +245,7 @@ describe("editProfile shoud update user", () => {
|
||||
session: defaultSession,
|
||||
});
|
||||
|
||||
await db.insert(schema.users).values({
|
||||
await db.insert(users).values({
|
||||
id: defaultOwnerId,
|
||||
name: "TEST 1",
|
||||
email: "abc@gmail.com",
|
||||
@@ -260,7 +260,7 @@ describe("editProfile shoud update user", () => {
|
||||
});
|
||||
|
||||
// assert
|
||||
const user = await db.select().from(schema.users).where(eq(schema.users.id, defaultOwnerId));
|
||||
const user = await db.select().from(users).where(eq(users.id, defaultOwnerId));
|
||||
|
||||
expect(user).toHaveLength(1);
|
||||
expect(user[0]).containSubset({
|
||||
@@ -295,11 +295,11 @@ describe("delete should delete user", () => {
|
||||
},
|
||||
];
|
||||
|
||||
await db.insert(schema.users).values(initialUsers);
|
||||
await db.insert(users).values(initialUsers);
|
||||
|
||||
await caller.delete({ userId: defaultOwnerId });
|
||||
|
||||
const usersInDb = await db.select().from(schema.users);
|
||||
const usersInDb = await db.select().from(users);
|
||||
expect(usersInDb).toHaveLength(2);
|
||||
expect(usersInDb[0]).containSubset(initialUsers[0]);
|
||||
expect(usersInDb[1]).containSubset(initialUsers[2]);
|
||||
|
||||
@@ -2,8 +2,8 @@ import { TRPCError } from "@trpc/server";
|
||||
|
||||
import { createSaltAsync, hashPasswordAsync } from "@homarr/auth";
|
||||
import type { Database } from "@homarr/db";
|
||||
import { and, createId, eq, like, schema } from "@homarr/db";
|
||||
import { groupMembers, groupPermissions, groups, invites, users } from "@homarr/db/schema/sqlite";
|
||||
import { and, createId, eq, like } from "@homarr/db";
|
||||
import { groupMembers, groupPermissions, groups, invites, users } from "@homarr/db/schema";
|
||||
import { selectUserSchema } from "@homarr/db/validationSchemas";
|
||||
import { credentialsAdminGroup } from "@homarr/definitions";
|
||||
import type { SupportedAuthProvider } from "@homarr/definitions";
|
||||
@@ -509,7 +509,7 @@ const createUserAsync = async (db: Database, input: Omit<z.infer<typeof validati
|
||||
const username = input.username.toLowerCase();
|
||||
|
||||
const userId = createId();
|
||||
await db.insert(schema.users).values({
|
||||
await db.insert(users).values({
|
||||
id: userId,
|
||||
name: username,
|
||||
email: input.email,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { observable } from "@trpc/server/observable";
|
||||
|
||||
import type { Modify } from "@homarr/common/types";
|
||||
import type { Integration } from "@homarr/db/schema/sqlite";
|
||||
import type { Integration } from "@homarr/db/schema";
|
||||
import type { IntegrationKindByCategory } from "@homarr/definitions";
|
||||
import { getIntegrationKindsByCategory } from "@homarr/definitions";
|
||||
import { integrationCreator } from "@homarr/integrations";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { observable } from "@trpc/server/observable";
|
||||
|
||||
import type { Modify } from "@homarr/common/types";
|
||||
import type { Integration } from "@homarr/db/schema/sqlite";
|
||||
import type { Integration } from "@homarr/db/schema";
|
||||
import type { IntegrationKindByCategory } from "@homarr/definitions";
|
||||
import { getIntegrationKindsByCategory } from "@homarr/definitions";
|
||||
import type { DownloadClientJobsAndStatus } from "@homarr/integrations";
|
||||
|
||||
@@ -2,7 +2,7 @@ import { TRPCError } from "@trpc/server";
|
||||
import SuperJSON from "superjson";
|
||||
|
||||
import { eq } from "@homarr/db";
|
||||
import { items } from "@homarr/db/schema/sqlite";
|
||||
import { items } from "@homarr/db/schema";
|
||||
import { z } from "@homarr/validation";
|
||||
|
||||
import { createTRPCRouter, protectedProcedure } from "../../trpc";
|
||||
|
||||
@@ -3,7 +3,7 @@ import { DrizzleAdapter } from "@auth/drizzle-adapter";
|
||||
|
||||
import type { Database } from "@homarr/db";
|
||||
import { and, eq } from "@homarr/db";
|
||||
import { accounts, sessions, users } from "@homarr/db/schema/sqlite";
|
||||
import { accounts, sessions, users } from "@homarr/db/schema";
|
||||
import type { SupportedAuthProvider } from "@homarr/definitions";
|
||||
|
||||
export const createAdapter = (db: Database, provider: SupportedAuthProvider | "unknown"): Adapter => {
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { NextAuthConfig } from "next-auth";
|
||||
import type { Session } from "@homarr/auth";
|
||||
import type { Database } from "@homarr/db";
|
||||
import { eq, inArray } from "@homarr/db";
|
||||
import { groupMembers, groupPermissions, users } from "@homarr/db/schema/sqlite";
|
||||
import { groupMembers, groupPermissions, users } from "@homarr/db/schema";
|
||||
import { getPermissionsWithChildren } from "@homarr/definitions";
|
||||
|
||||
export const getCurrentUserPermissionsAsync = async (db: Database, userId: string) => {
|
||||
|
||||
@@ -4,7 +4,7 @@ import type { NextAuthConfig } from "next-auth";
|
||||
|
||||
import { and, eq, inArray } from "@homarr/db";
|
||||
import type { Database } from "@homarr/db";
|
||||
import { groupMembers, groups, users } from "@homarr/db/schema/sqlite";
|
||||
import { groupMembers, groups, users } from "@homarr/db/schema";
|
||||
import { colorSchemeCookieKey, everyoneGroup } from "@homarr/definitions";
|
||||
import { logger } from "@homarr/log";
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
"bcrypt": "^5.1.1",
|
||||
"cookies": "^0.9.1",
|
||||
"ldapts": "7.3.0",
|
||||
"next": "^14.2.20",
|
||||
"next": "^14.2.21",
|
||||
"next-auth": "5.0.0-beta.25",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0"
|
||||
|
||||
@@ -2,7 +2,7 @@ import type { Session } from "next-auth";
|
||||
|
||||
import type { Database } from "@homarr/db";
|
||||
import { and, eq, inArray, or } from "@homarr/db";
|
||||
import { boards, boardUserPermissions, groupMembers } from "@homarr/db/schema/sqlite";
|
||||
import { boards, boardUserPermissions, groupMembers } from "@homarr/db/schema";
|
||||
import type { IntegrationPermission } from "@homarr/definitions";
|
||||
|
||||
import { constructIntegrationPermissions } from "./integration-permissions";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Session } from "next-auth";
|
||||
|
||||
import { db, eq, inArray } from "@homarr/db";
|
||||
import { groupMembers, integrationGroupPermissions, integrationUserPermissions } from "@homarr/db/schema/sqlite";
|
||||
import { groupMembers, integrationGroupPermissions, integrationUserPermissions } from "@homarr/db/schema";
|
||||
|
||||
import { constructIntegrationPermissions } from "./integration-permissions";
|
||||
|
||||
|
||||
@@ -3,14 +3,7 @@ import { describe, expect, test, vi } from "vitest";
|
||||
|
||||
import type { InferInsertModel } from "@homarr/db";
|
||||
import { createId } from "@homarr/db";
|
||||
import {
|
||||
boardGroupPermissions,
|
||||
boards,
|
||||
boardUserPermissions,
|
||||
groupMembers,
|
||||
groups,
|
||||
users,
|
||||
} from "@homarr/db/schema/sqlite";
|
||||
import { boardGroupPermissions, boards, boardUserPermissions, groupMembers, groups, users } from "@homarr/db/schema";
|
||||
import { createDb } from "@homarr/db/test";
|
||||
|
||||
import * as integrationPermissions from "../integration-permissions";
|
||||
|
||||
@@ -2,7 +2,7 @@ import bcrypt from "bcrypt";
|
||||
|
||||
import type { Database } from "@homarr/db";
|
||||
import { and, eq } from "@homarr/db";
|
||||
import { users } from "@homarr/db/schema/sqlite";
|
||||
import { users } from "@homarr/db/schema";
|
||||
import { logger } from "@homarr/log";
|
||||
import type { validation, z } from "@homarr/validation";
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import { CredentialsSignin } from "@auth/core/errors";
|
||||
|
||||
import type { Database, InferInsertModel } from "@homarr/db";
|
||||
import { and, createId, eq } from "@homarr/db";
|
||||
import { users } from "@homarr/db/schema/sqlite";
|
||||
import { users } from "@homarr/db/schema";
|
||||
import { logger } from "@homarr/log";
|
||||
import type { validation } from "@homarr/validation";
|
||||
import { z } from "@homarr/validation";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import { createId } from "@homarr/db";
|
||||
import { users } from "@homarr/db/schema/sqlite";
|
||||
import { users } from "@homarr/db/schema";
|
||||
import { createDb } from "@homarr/db/test";
|
||||
|
||||
import { createSaltAsync, hashPasswordAsync } from "../../security";
|
||||
|
||||
@@ -3,7 +3,7 @@ import { describe, expect, test, vi } from "vitest";
|
||||
|
||||
import type { Database } from "@homarr/db";
|
||||
import { and, createId, eq } from "@homarr/db";
|
||||
import { groups, users } from "@homarr/db/schema/sqlite";
|
||||
import { groups, users } from "@homarr/db/schema";
|
||||
import { createDb } from "@homarr/db/test";
|
||||
|
||||
import { authorizeWithLdapCredentialsAsync } from "../credentials/authorization/ldap-authorization";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { describe, expect, test } from "vitest";
|
||||
|
||||
import { users } from "@homarr/db/schema/sqlite";
|
||||
import { users } from "@homarr/db/schema";
|
||||
import { createDb } from "@homarr/db/test";
|
||||
|
||||
import { createAdapter } from "../adapter";
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { AdapterUser } from "@auth/core/adapters";
|
||||
import type { JWT } from "next-auth/jwt";
|
||||
import { describe, expect, test, vi } from "vitest";
|
||||
|
||||
import { groupMembers, groupPermissions, groups, users } from "@homarr/db/schema/sqlite";
|
||||
import { groupMembers, groupPermissions, groups, users } from "@homarr/db/schema";
|
||||
import { createDb } from "@homarr/db/test";
|
||||
import * as definitions from "@homarr/definitions";
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import { describe, expect, test, vi } from "vitest";
|
||||
|
||||
import { eq } from "@homarr/db";
|
||||
import type { Database } from "@homarr/db";
|
||||
import { groupMembers, groups, users } from "@homarr/db/schema/sqlite";
|
||||
import { groupMembers, groups, users } from "@homarr/db/schema";
|
||||
import { createDb } from "@homarr/db/test";
|
||||
import { colorSchemeCookieKey, everyoneGroup } from "@homarr/definitions";
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@ import { command, string } from "@drizzle-team/brocli";
|
||||
import { hashPasswordAsync } from "@homarr/auth";
|
||||
import { generateSecureRandomToken } from "@homarr/common/server";
|
||||
import { and, db, eq } from "@homarr/db";
|
||||
import { sessions, users } from "@homarr/db/schema/sqlite";
|
||||
import { sessions, users } from "@homarr/db/schema";
|
||||
|
||||
export const resetPassword = command({
|
||||
name: "reset-password",
|
||||
|
||||
@@ -27,9 +27,9 @@
|
||||
"dependencies": {
|
||||
"@homarr/log": "workspace:^0.1.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"next": "^14.2.20",
|
||||
"next": "^14.2.21",
|
||||
"react": "^19.0.0",
|
||||
"tldts": "^6.1.68"
|
||||
"tldts": "^6.1.69"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
|
||||
@@ -3,7 +3,7 @@ import { EVERY_WEEK } from "@homarr/cron-jobs-core/expressions";
|
||||
import type { InferInsertModel } from "@homarr/db";
|
||||
import { db, inArray } from "@homarr/db";
|
||||
import { createId } from "@homarr/db/client";
|
||||
import { iconRepositories, icons } from "@homarr/db/schema/sqlite";
|
||||
import { iconRepositories, icons } from "@homarr/db/schema";
|
||||
import { fetchIconsAsync } from "@homarr/icons";
|
||||
import { logger } from "@homarr/log";
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ import SuperJSON from "superjson";
|
||||
import type { Modify } from "@homarr/common/types";
|
||||
import { EVERY_5_MINUTES } from "@homarr/cron-jobs-core/expressions";
|
||||
import { db, eq } from "@homarr/db";
|
||||
import { items } from "@homarr/db/schema/sqlite";
|
||||
import { items } from "@homarr/db/schema";
|
||||
import { logger } from "@homarr/log";
|
||||
import { createItemChannel } from "@homarr/redis";
|
||||
import { z } from "@homarr/validation";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { env } from "@homarr/auth/env.mjs";
|
||||
import { NEVER } from "@homarr/cron-jobs-core/expressions";
|
||||
import { db, eq, inArray } from "@homarr/db";
|
||||
import { sessions, users } from "@homarr/db/schema/sqlite";
|
||||
import { sessions, users } from "@homarr/db/schema";
|
||||
import { supportedAuthProviders } from "@homarr/definitions";
|
||||
import { logger } from "@homarr/log";
|
||||
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
/* eslint-disable @typescript-eslint/no-non-null-assertion */
|
||||
import * as dotenv from "dotenv";
|
||||
import type { Config } from "drizzle-kit";
|
||||
|
||||
dotenv.config({ path: "../../.env" });
|
||||
import { env } from "../env.mjs";
|
||||
|
||||
export default {
|
||||
dialect: "mysql",
|
||||
schema: "./schema",
|
||||
casing: "snake_case",
|
||||
dbCredentials: {
|
||||
host: process.env.DB_HOST!,
|
||||
user: process.env.DB_USER!,
|
||||
password: process.env.DB_PASSWORD!,
|
||||
database: process.env.DB_NAME!,
|
||||
port: parseInt(process.env.DB_PORT!),
|
||||
},
|
||||
dbCredentials: env.DB_URL
|
||||
? { url: env.DB_URL }
|
||||
: {
|
||||
host: env.DB_HOST,
|
||||
user: env.DB_USER,
|
||||
password: env.DB_PASSWORD,
|
||||
database: env.DB_NAME,
|
||||
port: env.DB_PORT,
|
||||
},
|
||||
out: "./migrations/mysql",
|
||||
} satisfies Config;
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
import * as dotenv from "dotenv";
|
||||
import type { Config } from "drizzle-kit";
|
||||
|
||||
dotenv.config({ path: "../../.env" });
|
||||
import { env } from "../env.mjs";
|
||||
|
||||
export default {
|
||||
dialect: "sqlite",
|
||||
schema: "./schema",
|
||||
casing: "snake_case",
|
||||
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
||||
dbCredentials: { url: process.env.DB_URL! },
|
||||
dbCredentials: { url: env.DB_URL },
|
||||
out: "./migrations/sqlite",
|
||||
} satisfies Config;
|
||||
|
||||
@@ -7,6 +7,7 @@ import mysql from "mysql2";
|
||||
|
||||
import { logger } from "@homarr/log";
|
||||
|
||||
import { env } from "./env.mjs";
|
||||
import * as mysqlSchema from "./schema/mysql";
|
||||
import * as sqliteSchema from "./schema/sqlite";
|
||||
|
||||
@@ -15,7 +16,7 @@ type HomarrDatabase = BetterSQLite3Database<typeof sqliteSchema>;
|
||||
const init = () => {
|
||||
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
|
||||
if (!connection) {
|
||||
switch (process.env.DB_DRIVER) {
|
||||
switch (env.DB_DRIVER) {
|
||||
case "mysql2":
|
||||
initMySQL2();
|
||||
break;
|
||||
@@ -36,7 +37,7 @@ class WinstonDrizzleLogger implements Logger {
|
||||
}
|
||||
|
||||
const initBetterSqlite = () => {
|
||||
connection = new Database(process.env.DB_URL);
|
||||
connection = new Database(env.DB_URL);
|
||||
database = drizzleSqlite(connection, {
|
||||
schema: sqliteSchema,
|
||||
logger: new WinstonDrizzleLogger(),
|
||||
@@ -45,16 +46,15 @@ const initBetterSqlite = () => {
|
||||
};
|
||||
|
||||
const initMySQL2 = () => {
|
||||
if (!process.env.DB_HOST) {
|
||||
connection = mysql.createConnection({ uri: process.env.DB_URL });
|
||||
if (!env.DB_HOST) {
|
||||
connection = mysql.createConnection({ uri: env.DB_URL });
|
||||
} 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,
|
||||
password: process.env.DB_PASSWORD,
|
||||
host: env.DB_HOST,
|
||||
database: env.DB_NAME,
|
||||
port: env.DB_PORT,
|
||||
user: env.DB_USER,
|
||||
password: env.DB_PASSWORD,
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
60
packages/db/env.mjs
Normal file
60
packages/db/env.mjs
Normal file
@@ -0,0 +1,60 @@
|
||||
import { createEnv } from "@t3-oss/env-nextjs";
|
||||
import { z } from "zod";
|
||||
|
||||
const drivers = {
|
||||
betterSqlite3: "better-sqlite3",
|
||||
mysql2: "mysql2",
|
||||
};
|
||||
|
||||
const isDriver = (driver) => process.env.DB_DRIVER === driver;
|
||||
const isUsingDbHost = Boolean(process.env.DB_HOST);
|
||||
const onlyAllowUrl = isDriver(drivers.betterSqlite3);
|
||||
const urlRequired = onlyAllowUrl || !isUsingDbHost;
|
||||
const hostRequired = isUsingDbHost && !onlyAllowUrl;
|
||||
|
||||
export const env = createEnv({
|
||||
/**
|
||||
* Specify your server-side environment variables schema here. This way you can ensure the app isn't
|
||||
* built with invalid env vars.
|
||||
*/
|
||||
server: {
|
||||
DB_DRIVER: z
|
||||
.union([z.literal(drivers.betterSqlite3), z.literal(drivers.mysql2)], {
|
||||
message: `Invalid database driver, supported are ${Object.keys(drivers).join(", ")}`,
|
||||
})
|
||||
.default(drivers.betterSqlite3),
|
||||
...(urlRequired
|
||||
? {
|
||||
DB_URL: z.string(),
|
||||
}
|
||||
: {}),
|
||||
...(hostRequired
|
||||
? {
|
||||
DB_HOST: z.string(),
|
||||
DB_PORT: z
|
||||
.string()
|
||||
.regex(/\d+/)
|
||||
.transform(Number)
|
||||
.refine((number) => number >= 1)
|
||||
.default("3306"),
|
||||
DB_USER: z.string(),
|
||||
DB_PASSWORD: z.string(),
|
||||
DB_NAME: z.string(),
|
||||
}
|
||||
: {}),
|
||||
},
|
||||
/**
|
||||
* Destructure all variables from `process.env` to make sure they aren't tree-shaken away.
|
||||
*/
|
||||
runtimeEnv: {
|
||||
DB_DRIVER: process.env.DB_DRIVER,
|
||||
DB_URL: process.env.DB_URL,
|
||||
DB_HOST: process.env.DB_HOST,
|
||||
DB_USER: process.env.DB_USER,
|
||||
DB_PASSWORD: process.env.DB_PASSWORD,
|
||||
DB_NAME: process.env.DB_NAME,
|
||||
DB_PORT: process.env.DB_PORT,
|
||||
},
|
||||
skipValidation:
|
||||
Boolean(process.env.CI) || Boolean(process.env.SKIP_ENV_VALIDATION) || process.env.npm_lifecycle_event === "lint",
|
||||
});
|
||||
@@ -1,10 +1,6 @@
|
||||
import Database from "better-sqlite3";
|
||||
|
||||
import { database } from "./driver";
|
||||
import * as sqliteSchema from "./schema/sqlite";
|
||||
|
||||
// Export only the types from the sqlite schema as we're using that.
|
||||
export const schema = sqliteSchema;
|
||||
|
||||
export * from "drizzle-orm";
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
/* 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";
|
||||
|
||||
import type { Database } from "../..";
|
||||
import { env } from "../../env.mjs";
|
||||
import * as mysqlSchema from "../../schema/mysql";
|
||||
import { seedDataAsync } from "../seed";
|
||||
|
||||
@@ -11,15 +11,15 @@ const migrationsFolder = process.argv[2] ?? ".";
|
||||
|
||||
const migrateAsync = async () => {
|
||||
const mysql2 = mysql.createConnection(
|
||||
process.env.DB_HOST
|
||||
? {
|
||||
host: process.env.DB_HOST,
|
||||
database: process.env.DB_NAME!,
|
||||
port: Number(process.env.DB_PORT),
|
||||
user: process.env.DB_USER,
|
||||
password: process.env.DB_PASSWORD,
|
||||
}
|
||||
: { uri: process.env.DB_URL },
|
||||
env.DB_URL
|
||||
? { uri: env.DB_URL }
|
||||
: {
|
||||
host: env.DB_HOST,
|
||||
database: env.DB_NAME,
|
||||
port: env.DB_PORT,
|
||||
user: env.DB_USER,
|
||||
password: env.DB_PASSWORD,
|
||||
},
|
||||
);
|
||||
|
||||
const db = drizzle(mysql2, {
|
||||
|
||||
@@ -6,8 +6,8 @@ import { defaultServerSettings, defaultServerSettingsKeys } from "@homarr/server
|
||||
|
||||
import { createId, eq } from "..";
|
||||
import type { Database } from "..";
|
||||
import { onboarding, serverSettings } from "../schema";
|
||||
import { groups } from "../schema/mysql";
|
||||
import { onboarding, serverSettings } from "../schema/sqlite";
|
||||
|
||||
export const seedDataAsync = async (db: Database) => {
|
||||
await seedEveryoneGroupAsync(db);
|
||||
|
||||
@@ -2,15 +2,16 @@ import Database from "better-sqlite3";
|
||||
import { drizzle } from "drizzle-orm/better-sqlite3";
|
||||
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
|
||||
|
||||
import { schema } from "../..";
|
||||
import { env } from "../../env.mjs";
|
||||
import * as sqliteSchema from "../../schema/sqlite";
|
||||
import { seedDataAsync } from "../seed";
|
||||
|
||||
const migrationsFolder = process.argv[2] ?? ".";
|
||||
|
||||
const migrateAsync = async () => {
|
||||
const sqlite = new Database(process.env.DB_URL?.replace("file:", ""));
|
||||
const sqlite = new Database(env.DB_URL.replace("file:", ""));
|
||||
|
||||
const db = drizzle(sqlite, { schema, casing: "snake_case" });
|
||||
const db = drizzle(sqlite, { schema: sqliteSchema, casing: "snake_case" });
|
||||
|
||||
migrate(db, { migrationsFolder });
|
||||
|
||||
|
||||
@@ -7,10 +7,11 @@
|
||||
"exports": {
|
||||
".": "./index.ts",
|
||||
"./client": "./client.ts",
|
||||
"./schema/sqlite": "./schema/sqlite.ts",
|
||||
"./schema": "./schema/index.ts",
|
||||
"./test": "./test/index.ts",
|
||||
"./queries": "./queries/index.ts",
|
||||
"./validationSchemas": "./validationSchemas.ts"
|
||||
"./validationSchemas": "./validationSchemas.ts",
|
||||
"./env.mjs": "./env.mjs"
|
||||
},
|
||||
"main": "./index.ts",
|
||||
"types": "./index.ts",
|
||||
@@ -21,16 +22,16 @@
|
||||
"clean": "rm -rf .turbo node_modules",
|
||||
"format": "prettier --check . --ignore-path ../../.gitignore",
|
||||
"lint": "eslint",
|
||||
"migration:mysql:drop": "drizzle-kit drop --config ./configs/mysql.config.ts",
|
||||
"migration:mysql:generate": "drizzle-kit generate --config ./configs/mysql.config.ts",
|
||||
"migration:mysql:run": "drizzle-kit migrate --config ./configs/mysql.config.ts && pnpm run seed",
|
||||
"migration:sqlite:drop": "drizzle-kit drop --config ./configs/sqlite.config.ts",
|
||||
"migration:sqlite:generate": "drizzle-kit generate --config ./configs/sqlite.config.ts",
|
||||
"migration:sqlite:run": "drizzle-kit migrate --config ./configs/sqlite.config.ts && pnpm run seed",
|
||||
"push:mysql": "drizzle-kit push --config ./configs/mysql.config.ts",
|
||||
"push:sqlite": "drizzle-kit push --config ./configs/sqlite.config.ts",
|
||||
"migration:mysql:drop": "pnpm with-env drizzle-kit drop --config ./configs/mysql.config.ts",
|
||||
"migration:mysql:generate": "pnpm with-env drizzle-kit generate --config ./configs/mysql.config.ts",
|
||||
"migration:mysql:run": "pnpm with-env drizzle-kit migrate --config ./configs/mysql.config.ts && pnpm run seed",
|
||||
"migration:sqlite:drop": "pnpm with-env drizzle-kit drop --config ./configs/sqlite.config.ts",
|
||||
"migration:sqlite:generate": "pnpm with-env drizzle-kit generate --config ./configs/sqlite.config.ts",
|
||||
"migration:sqlite:run": "pnpm with-env drizzle-kit migrate --config ./configs/sqlite.config.ts && pnpm run seed",
|
||||
"push:mysql": "pnpm with-env drizzle-kit push --config ./configs/mysql.config.ts",
|
||||
"push:sqlite": "pnpm with-env drizzle-kit push --config ./configs/sqlite.config.ts",
|
||||
"seed": "pnpm with-env tsx ./migrations/run-seed.ts",
|
||||
"studio": "drizzle-kit studio --config ./configs/sqlite.config.ts",
|
||||
"studio": "pnpm with-env drizzle-kit studio --config ./configs/sqlite.config.ts",
|
||||
"typecheck": "tsc --noEmit",
|
||||
"with-env": "dotenv -e ../../.env --"
|
||||
},
|
||||
@@ -42,6 +43,7 @@
|
||||
"@homarr/log": "workspace:^0.1.0",
|
||||
"@homarr/server-settings": "workspace:^0.1.0",
|
||||
"@paralleldrive/cuid2": "^2.2.2",
|
||||
"@t3-oss/env-nextjs": "^0.11.1",
|
||||
"@testcontainers/mysql": "^10.16.0",
|
||||
"better-sqlite3": "^11.7.0",
|
||||
"dotenv": "^16.4.7",
|
||||
|
||||
@@ -3,7 +3,7 @@ import type { WidgetKind } from "@homarr/definitions";
|
||||
import type { Database } from "..";
|
||||
import { inArray } from "..";
|
||||
import type { inferSupportedIntegrations } from "../../widgets/src";
|
||||
import { items } from "../schema/sqlite";
|
||||
import { items } from "../schema";
|
||||
|
||||
export const getItemsWithIntegrationsAsync = async <TKind extends WidgetKind>(
|
||||
db: Database,
|
||||
|
||||
@@ -5,7 +5,7 @@ import { defaultServerSettings, defaultServerSettingsKeys } from "@homarr/server
|
||||
|
||||
import type { Database } from "..";
|
||||
import { eq } from "..";
|
||||
import { serverSettings } from "../schema/sqlite";
|
||||
import { serverSettings } from "../schema";
|
||||
|
||||
export const getServerSettingsAsync = async (db: Database) => {
|
||||
const settings = await db.query.serverSettings.findMany();
|
||||
|
||||
45
packages/db/schema/index.ts
Normal file
45
packages/db/schema/index.ts
Normal file
@@ -0,0 +1,45 @@
|
||||
import type { InferSelectModel } from "drizzle-orm";
|
||||
|
||||
import * as mysqlSchema from "./mysql";
|
||||
import * as sqliteSchema from "./sqlite";
|
||||
|
||||
type Schema = typeof sqliteSchema;
|
||||
|
||||
const schema = process.env.DB_DRIVER === "mysql2" ? (mysqlSchema as unknown as Schema) : sqliteSchema;
|
||||
|
||||
// Sadly we can't use export * from here as we have multiple possible exports
|
||||
export const {
|
||||
accounts,
|
||||
apiKeys,
|
||||
apps,
|
||||
boardGroupPermissions,
|
||||
boardUserPermissions,
|
||||
boards,
|
||||
groupMembers,
|
||||
groupPermissions,
|
||||
groups,
|
||||
iconRepositories,
|
||||
icons,
|
||||
integrationGroupPermissions,
|
||||
integrationItems,
|
||||
integrationSecrets,
|
||||
integrationUserPermissions,
|
||||
integrations,
|
||||
invites,
|
||||
items,
|
||||
medias,
|
||||
onboarding,
|
||||
searchEngines,
|
||||
sections,
|
||||
serverSettings,
|
||||
sessions,
|
||||
users,
|
||||
verificationTokens,
|
||||
} = schema;
|
||||
|
||||
export type User = InferSelectModel<typeof schema.users>;
|
||||
export type Account = InferSelectModel<typeof schema.accounts>;
|
||||
export type Session = InferSelectModel<typeof schema.sessions>;
|
||||
export type VerificationToken = InferSelectModel<typeof schema.verificationTokens>;
|
||||
export type Integration = InferSelectModel<typeof schema.integrations>;
|
||||
export type IntegrationSecret = InferSelectModel<typeof schema.integrationSecrets>;
|
||||
@@ -1,6 +1,5 @@
|
||||
import type { AdapterAccount } from "@auth/core/adapters";
|
||||
import type { DayOfWeek } from "@mantine/dates";
|
||||
import type { InferSelectModel } from "drizzle-orm";
|
||||
import { relations, sql } from "drizzle-orm";
|
||||
import type { AnySQLiteColumn } from "drizzle-orm/sqlite-core";
|
||||
import { blob, index, int, primaryKey, sqliteTable, text } from "drizzle-orm/sqlite-core";
|
||||
@@ -567,10 +566,3 @@ export const searchEngineRelations = relations(searchEngines, ({ one }) => ({
|
||||
references: [integrations.id],
|
||||
}),
|
||||
}));
|
||||
|
||||
export type User = InferSelectModel<typeof users>;
|
||||
export type Account = InferSelectModel<typeof accounts>;
|
||||
export type Session = InferSelectModel<typeof sessions>;
|
||||
export type VerificationToken = InferSelectModel<typeof verificationTokens>;
|
||||
export type Integration = InferSelectModel<typeof integrations>;
|
||||
export type IntegrationSecret = InferSelectModel<typeof integrationSecrets>;
|
||||
|
||||
@@ -2,11 +2,11 @@ import Database from "better-sqlite3";
|
||||
import { drizzle } from "drizzle-orm/better-sqlite3";
|
||||
import { migrate } from "drizzle-orm/better-sqlite3/migrator";
|
||||
|
||||
import { schema } from "..";
|
||||
import * as sqliteSchema from "../schema/sqlite";
|
||||
|
||||
export const createDb = (debug?: boolean) => {
|
||||
const sqlite = new Database(":memory:");
|
||||
const db = drizzle(sqlite, { schema, logger: debug, casing: "snake_case" });
|
||||
const db = drizzle(sqlite, { schema: sqliteSchema, logger: debug, casing: "snake_case" });
|
||||
migrate(db, {
|
||||
migrationsFolder: "./packages/db/migrations/sqlite",
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createSelectSchema } from "drizzle-zod";
|
||||
|
||||
import { apps, boards, groups, invites, searchEngines, serverSettings, users } from "./schema/sqlite";
|
||||
import { apps, boards, groups, invites, searchEngines, serverSettings, users } from "./schema";
|
||||
|
||||
export const selectAppSchema = createSelectSchema(apps);
|
||||
export const selectBoardSchema = createSelectSchema(boards);
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { decryptSecret } from "@homarr/common/server";
|
||||
import type { Modify } from "@homarr/common/types";
|
||||
import type { Integration as DbIntegration } from "@homarr/db/schema/sqlite";
|
||||
import type { Integration as DbIntegration } from "@homarr/db/schema";
|
||||
import type { IntegrationKind, IntegrationSecretKind } from "@homarr/definitions";
|
||||
|
||||
import { AdGuardHomeIntegration } from "../adguard-home/adguard-home-integration";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Integration } from "@homarr/db/schema/sqlite";
|
||||
import type { Integration } from "@homarr/db/schema";
|
||||
import { z } from "@homarr/validation";
|
||||
|
||||
const usenetQueueState = ["downloading", "queued", "paused"] as const;
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import type { Integration } from "@homarr/db/schema/sqlite";
|
||||
import type { Integration } from "@homarr/db/schema";
|
||||
|
||||
export interface DownloadClientStatus {
|
||||
/** If client is considered paused */
|
||||
|
||||
@@ -35,7 +35,7 @@
|
||||
"@mantine/core": "^7.15.1",
|
||||
"@tabler/icons-react": "^3.26.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"next": "^14.2.20",
|
||||
"next": "^14.2.21",
|
||||
"react": "^19.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
||||
@@ -40,11 +40,11 @@
|
||||
"@mantine/core": "^7.15.1",
|
||||
"@mantine/hooks": "^7.15.1",
|
||||
"adm-zip": "0.5.16",
|
||||
"next": "^14.2.20",
|
||||
"next": "^14.2.21",
|
||||
"react": "^19.0.0",
|
||||
"superjson": "2.2.2",
|
||||
"zod": "^3.24.1",
|
||||
"zod-form-data": "^2.0.2"
|
||||
"zod-form-data": "^2.0.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@homarr/eslint-config": "workspace:^0.2.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createId, inArray } from "@homarr/db";
|
||||
import type { Database, InferInsertModel, InferSelectModel } from "@homarr/db";
|
||||
import { apps as appsTable } from "@homarr/db/schema/sqlite";
|
||||
import { apps as appsTable } from "@homarr/db/schema";
|
||||
import { logger } from "@homarr/log";
|
||||
import type { OldmarrApp } from "@homarr/old-schema";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { Database } from "@homarr/db";
|
||||
import { createId } from "@homarr/db";
|
||||
import { boards } from "@homarr/db/schema/sqlite";
|
||||
import { boards } from "@homarr/db/schema";
|
||||
import { logger } from "@homarr/log";
|
||||
import type { OldmarrConfig } from "@homarr/old-schema";
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ import SuperJSON from "superjson";
|
||||
|
||||
import type { Database } from "@homarr/db";
|
||||
import { createId } from "@homarr/db";
|
||||
import { items } from "@homarr/db/schema/sqlite";
|
||||
import { items } from "@homarr/db/schema";
|
||||
import { logger } from "@homarr/log";
|
||||
import type { OldmarrApp, OldmarrWidget } from "@homarr/old-schema";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createId } from "@homarr/db";
|
||||
import type { Database } from "@homarr/db";
|
||||
import { sections } from "@homarr/db/schema/sqlite";
|
||||
import { sections } from "@homarr/db/schema";
|
||||
import { logger } from "@homarr/log";
|
||||
import type { OldmarrConfig } from "@homarr/old-schema";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { objectEntries } from "@homarr/common";
|
||||
import type { Database, InferInsertModel } from "@homarr/db";
|
||||
import { schema } from "@homarr/db";
|
||||
import * as schema from "@homarr/db/schema";
|
||||
|
||||
type TableKey = {
|
||||
[K in keyof typeof schema]: (typeof schema)[K] extends { _: { brand: "Table" } } ? K : never;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { inArray } from "@homarr/db";
|
||||
import type { Database } from "@homarr/db";
|
||||
import { apps } from "@homarr/db/schema/sqlite";
|
||||
import { apps } from "@homarr/db/schema";
|
||||
import type { OldmarrConfig } from "@homarr/old-schema";
|
||||
|
||||
import { doAppsMatch } from "../prepare/prepare-apps";
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { InferSelectModel } from "@homarr/db";
|
||||
import type { apps } from "@homarr/db/schema/sqlite";
|
||||
import type { apps } from "@homarr/db/schema";
|
||||
import type { OldmarrApp } from "@homarr/old-schema";
|
||||
|
||||
import type { OldmarrBookmarkDefinition } from "../widgets/definitions/bookmark";
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { InferInsertModel } from "@homarr/db";
|
||||
import { createId } from "@homarr/db";
|
||||
import type { boards } from "@homarr/db/schema/sqlite";
|
||||
import type { boards } from "@homarr/db/schema";
|
||||
|
||||
import type { prepareMultipleImports } from "../prepare/prepare-multiple";
|
||||
import { mapColor } from "./map-colors";
|
||||
|
||||
@@ -2,7 +2,7 @@ import SuperJSON from "superjson";
|
||||
|
||||
import type { InferInsertModel } from "@homarr/db";
|
||||
import { createId } from "@homarr/db";
|
||||
import type { items } from "@homarr/db/schema/sqlite";
|
||||
import type { items } from "@homarr/db/schema";
|
||||
import { logger } from "@homarr/log";
|
||||
import type { BoardSize, OldmarrApp, OldmarrWidget } from "@homarr/old-schema";
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import type { InferInsertModel } from "@homarr/db";
|
||||
import { createId } from "@homarr/db";
|
||||
import type { sections } from "@homarr/db/schema/sqlite";
|
||||
import type { sections } from "@homarr/db/schema";
|
||||
import type { OldmarrCategorySection, OldmarrEmptySection } from "@homarr/old-schema";
|
||||
|
||||
export const mapCategorySection = (
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { decryptSecretWithKey } from "@homarr/common/server";
|
||||
import type { InferInsertModel } from "@homarr/db";
|
||||
import { createId } from "@homarr/db";
|
||||
import type { users } from "@homarr/db/schema/sqlite";
|
||||
import type { users } from "@homarr/db/schema";
|
||||
|
||||
import type { OldmarrImportUser } from "../user-schema";
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { InferSelectModel } from "@homarr/db";
|
||||
import type { apps } from "@homarr/db/schema/sqlite";
|
||||
import type { apps } from "@homarr/db/schema";
|
||||
import type { OldmarrConfig } from "@homarr/old-schema";
|
||||
|
||||
import type { ValidAnalyseConfig } from "../analyse/types";
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Duration } from "dayjs/plugin/duration";
|
||||
|
||||
import type { Modify } from "@homarr/common/types";
|
||||
import type { Integration, IntegrationSecret } from "@homarr/db/schema/sqlite";
|
||||
import type { Integration, IntegrationSecret } from "@homarr/db/schema";
|
||||
import type { IntegrationKind } from "@homarr/definitions";
|
||||
import { createIntegrationOptionsChannel } from "@homarr/redis";
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@
|
||||
"@mantine/spotlight": "^7.15.1",
|
||||
"@tabler/icons-react": "^3.26.0",
|
||||
"jotai": "^2.10.4",
|
||||
"next": "^14.2.20",
|
||||
"next": "^14.2.21",
|
||||
"react": "^19.0.0",
|
||||
"use-deep-compare-effect": "^1.8.1"
|
||||
},
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
"dayjs": "^1.11.13",
|
||||
"deepmerge": "4.3.1",
|
||||
"mantine-react-table": "2.0.0-beta.7",
|
||||
"next": "^14.2.20",
|
||||
"next": "^14.2.21",
|
||||
"next-intl": "3.26.2",
|
||||
"react": "^19.0.0"
|
||||
},
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user