chore: various cleanups and deprecations fixes (#1437)

This commit is contained in:
Nicolas Meienberger 2024-05-26 16:15:13 +02:00 committed by GitHub
parent 3299259765
commit 74bff627fa
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
20 changed files with 66 additions and 660 deletions

View File

@ -16,3 +16,4 @@
!src/**
!tests/**
!start.*.sh
!scripts/**

View File

@ -2,6 +2,7 @@ module.exports = {
plugins: ['@typescript-eslint', 'import', 'react', 'jsx-a11y'],
extends: [
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
'next/core-web-vitals',
'plugin:import/typescript',
'plugin:react/recommended',

3
.gitignore vendored
View File

@ -70,3 +70,6 @@ temp
# Sentry Config File
.sentryclirc
public/js/*
!public/js/.gitkeep

3
.prettierignore Normal file
View File

@ -0,0 +1,3 @@
packages
coverage
.github

View File

@ -34,12 +34,13 @@ RUN pnpm fetch
COPY ./pnpm-workspace.yaml ./
COPY ./package*.json ./
COPY ./packages/shared ./packages/shared
COPY ./scripts ./scripts
COPY ./public ./public
RUN pnpm install -r --prefer-offline
COPY ./src ./src
COPY ./tsconfig.json ./tsconfig.json
COPY ./next.config.mjs ./next.config.mjs
COPY ./public ./public
COPY ./tests ./tests
# Sentry

View File

@ -32,13 +32,14 @@ RUN pnpm fetch --ignore-scripts
COPY ./package*.json ./
COPY ./packages/worker/package.json ./packages/worker/package.json
COPY ./packages/shared/package.json ./packages/shared/package.json
COPY ./scripts ./scripts
COPY ./public ./public
RUN pnpm install -r --prefer-offline
COPY ./packages ./packages
COPY ./tsconfig.json ./tsconfig.json
COPY ./next.config.mjs ./next.config.mjs
COPY ./public ./public
# Sentry
COPY ./sentry.client.config.ts ./sentry.client.config.ts

View File

@ -1,53 +0,0 @@
import nextJest from 'next/jest';
const createJestConfig = nextJest({
// Provide the path to your Next.js app to load next.config.js and .env files in your test environment
dir: './',
});
const customClientConfig = {
testEnvironment: 'jest-environment-jsdom',
setupFilesAfterEnv: ['<rootDir>/tests/client/jest.setup.tsx'],
testMatch: [
'<rootDir>/src/client/**/*.{spec,test}.{ts,tsx}',
'<rootDir>/src/app/**/*.{spec,test}.{ts,tsx}',
'!<rootDir>/src/server/**/*.{spec,test}.{ts,tsx}',
],
};
const customServerConfig = {
testEnvironment: 'node',
testMatch: ['<rootDir>/src/server/**/*.test.ts'],
setupFilesAfterEnv: ['<rootDir>/tests/server/jest.setup.ts'],
globals: {
fetch,
},
};
export default async () => {
const clientConfig = await createJestConfig(customClientConfig)();
const serverConfig = await createJestConfig(customServerConfig)();
return {
randomize: true,
verbose: true,
collectCoverage: true,
collectCoverageFrom: [
'src/server/**/*.{ts,tsx}',
'src/client/**/*.{ts,tsx}',
'!src/**/mocks/**/*.{ts,tsx}',
'!**/*.{spec,test}.{ts,tsx}',
'!**/index.{ts,tsx}',
],
projects: [
{
displayName: 'client',
...clientConfig,
},
{
displayName: 'server',
...serverConfig,
},
],
};
};

View File

@ -9,27 +9,20 @@
"test:ui": "dotenv -e .env.test -- vitest --ui",
"test:e2e": "NODE_ENV=test dotenv -e .env -e .env.e2e -- playwright test",
"test:e2e:ui": "NODE_ENV=test dotenv -e .env -e .env.e2e -- playwright test --ui",
"test:client": "jest --colors --selectProjects client --",
"test:server": "jest --colors --selectProjects server --",
"test:vite": "dotenv -e .env.test -- vitest run --coverage",
"dev": "next dev --turbo",
"db:migrate": "NODE_ENV=development dotenv -e .env.local -- tsx ./src/server/run-migrations-dev.ts",
"lint": "next lint",
"lint:fix": "next lint --fix",
"build": "next build --experimental-build-mode compile",
"start": "NODE_ENV=production node server.js",
"start:dev-container": "./.devcontainer/filewatcher.sh && npm run start:dev",
"start:rc": "docker compose -f docker-compose.rc.yml --env-file .env up --build",
"start:dev": "docker compose -f docker-compose.dev.yml up --build",
"start:prod": "docker compose --env-file ./.env -f docker-compose.prod.yml up --build",
"start:pg": "docker run --name test-db -p 5433:5432 -d --rm -e POSTGRES_PASSWORD=postgres postgres:14",
"version": "echo $npm_package_version",
"release:rc": "./scripts/deploy/release-rc.sh",
"test:build": "docker buildx build --platform linux/amd64,linux/arm64 -t meienberger/runtipi:test .",
"test:build:arm64": "docker buildx build --platform linux/arm64 -t meienberger/runtipi:test .",
"test:build:arm7": "docker buildx build --platform linux/arm/v7 -t meienberger/runtipi:test .",
"test:build:amd64": "docker buildx build --platform linux/amd64 -t meienberger/runtipi:test .",
"tsc": "tsc"
"tsc": "tsc",
"gen:certs": "mkcert -key-file ./traefik/tls/key.pem -cert-file ./traefik/tls/cert.pem tipi.local \"*.tipi.local\"",
"prettier-check": "prettier --check .",
"postinstall": "./scripts/postinstall.sh"
},
"dependencies": {
"@hookform/resolvers": "^3.4.2",
@ -51,7 +44,6 @@
"argon2": "^0.40.1",
"bullmq": "^5.7.12",
"clsx": "^2.1.0",
"connect-redis": "^7.1.1",
"drizzle-orm": "^0.30.9",
"fs-extra": "^11.2.0",
"geist": "^1.3.0",
@ -100,7 +92,6 @@
"@total-typescript/ts-reset": "^0.5.1",
"@types/eslint": "^8.56.10",
"@types/fs-extra": "^11.0.4",
"@types/jest": "^29.5.12",
"@types/jsonwebtoken": "^9.0.6",
"@types/lodash.merge": "^4.6.9",
"@types/node": "20.12.12",
@ -108,7 +99,6 @@
"@types/react": "18.3.3",
"@types/react-dom": "18.3.0",
"@types/semver": "^7.5.8",
"@types/ssh2": "^1.15.0",
"@types/uuid": "^9.0.8",
"@types/validator": "^13.11.10",
"@typescript-eslint/eslint-plugin": "^7.0.0",
@ -120,7 +110,6 @@
"eslint": "8.57.0",
"eslint-config-next": "14.2.3",
"eslint-config-prettier": "^9.1.0",
"eslint-import-resolver-typescript": "^3.6.1",
"eslint-plugin-import": "^2.29.1",
"eslint-plugin-jest": "^28.5.0",
"eslint-plugin-jest-dom": "^5.4.0",
@ -129,19 +118,14 @@
"eslint-plugin-react": "^7.34.1",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-testing-library": "^6.2.2",
"eslint-plugin-vitest": "^0.5.4",
"jest": "^29.7.0",
"jest-environment-jsdom": "^29.7.0",
"jsdom": "^24.0.0",
"jsonc-eslint-parser": "^2.4.0",
"knip": "^5.9.4",
"memfs": "^4.8.2",
"msw": "^2.3.0",
"next-router-mock": "^0.9.13",
"prettier": "^3.2.5",
"ssh2": "^1.15.0",
"ts-jest": "^29.1.2",
"ts-node": "^10.9.2",
"tsx": "^4.10.2",
"typescript": "5.4.5",
"vite-tsconfig-paths": "^4.3.2",
"vitest": "^1.6.0",

View File

@ -25,7 +25,8 @@
],
"scripts": {
"lint": "eslint --ext .ts src",
"tsc": "tsc --noEmit"
"tsc": "tsc --noEmit",
"prettier-check": "prettier --check ."
},
"keywords": [],
"author": "",

View File

@ -10,7 +10,8 @@
"tsc": "tsc",
"dev": "dotenv -e ../../.env nodemon",
"knip": "knip",
"lint": "eslint . --ext .ts"
"lint": "eslint . --ext .ts",
"prettier-check": "prettier --check ."
},
"keywords": [],
"author": "",
@ -18,7 +19,6 @@
"devDependencies": {
"@faker-js/faker": "^8.4.1",
"@sentry/esbuild-plugin": "^2.17.0",
"@total-typescript/shoehorn": "^0.1.2",
"@types/web-push": "^3.6.3",
"@typescript-eslint/eslint-plugin": "^7.0.0",
"@typescript-eslint/parser": "^6.21.0",

File diff suppressed because it is too large Load Diff

0
public/js/.gitkeep Normal file
View File

3
scripts/postinstall.sh Executable file
View File

@ -0,0 +1,3 @@
#!/bin/sh
cp ./node_modules/@tabler/core/dist/js/tabler.min.js ./public/js/tabler.min.js

View File

@ -1,6 +1,5 @@
import { AppInfo } from '@runtipi/shared';
export type SortableColumns = keyof Pick<AppInfo, 'id'>;
export type SortDirection = 'asc' | 'desc';
export type AppTableData = Omit<AppInfo, 'description' | 'form_fields' | 'source' | 'status' | 'url_suffix' | 'version'>[];

View File

@ -45,7 +45,7 @@ export const Header: React.FC<IProps> = ({ isUpdateAvailable, authenticated = tr
return (
<header className="text-white navbar navbar-expand-md navbar-dark navbar-overlap d-print-none" data-bs-theme="dark">
<Script src="https://cdn.jsdelivr.net/npm/@tabler/core@latest/dist/js/tabler.min.js" async />
<Script src="/js/tabler.min.js" async />
<div className="container-xl">
<button className="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbar-menu">
<span className="navbar-toggler-icon" />

View File

@ -1,7 +1,6 @@
'use client';
import React, { ComponentProps } from 'react';
import { CookiesProvider } from 'next-client-cookies';
import React from 'react';
import { AbstractIntlMessages, NextIntlClientProvider } from 'next-intl';
import { QueryClient, QueryClientProvider } from 'react-query';
import { ThemeProvider } from './ThemeProvider';
@ -9,7 +8,6 @@ import { SocketProvider } from './SocketProvider/SocketProvider';
type Props = {
children: React.ReactNode;
cookies: ComponentProps<typeof CookiesProvider>['value'];
initialTheme?: string;
locale?: string;
messages: AbstractIntlMessages;
@ -17,18 +15,14 @@ type Props = {
const queryClient = new QueryClient({ defaultOptions: { queries: { refetchOnWindowFocus: false } } });
export const ClientProviders = ({ children, initialTheme, cookies, locale, messages }: Props) => {
export const ClientProviders = ({ children, initialTheme, locale, messages }: Props) => {
return (
<QueryClientProvider client={queryClient}>
<NextIntlClientProvider locale={locale} messages={messages} timeZone={Intl.DateTimeFormat().resolvedOptions().timeZone}>
<SocketProvider>
<CookiesProvider value={cookies}>
<ThemeProvider initialTheme={initialTheme}>{children}</ThemeProvider>
</CookiesProvider>
<ThemeProvider initialTheme={initialTheme}>{children}</ThemeProvider>
</SocketProvider>
</NextIntlClientProvider>
</QueryClientProvider>
);
};
export const ClientCookiesProvider: typeof CookiesProvider = (props) => <CookiesProvider {...props} />;

View File

@ -11,6 +11,7 @@ import clsx from 'clsx';
import { Toaster } from 'react-hot-toast';
import { getCurrentLocale } from '../utils/getCurrentLocale';
import { ClientProviders } from './components/ClientProviders';
import { CookiesProvider } from 'next-client-cookies/server';
export const metadata: Metadata = {
title: 'Tipi',
@ -30,13 +31,15 @@ export default async function RootLayout({ children }: { children: React.ReactNo
return (
<html lang={locale} className={clsx(GeistSans.className, 'border-top-wide border-primary')}>
<ClientProviders messages={mergedMessages} locale={locale} initialTheme={theme?.value} cookies={cookies().getAll()}>
<body data-bs-theme={theme?.value}>
<input type="hidden" value={JSON.stringify(clientSettings)} id="client-settings" />
{children}
<Toaster />
</body>
</ClientProviders>
<CookiesProvider>
<ClientProviders messages={mergedMessages} locale={locale} initialTheme={theme?.value}>
<body data-bs-theme={theme?.value}>
<input type="hidden" value={JSON.stringify(clientSettings)} id="client-settings" />
{children}
<Toaster />
</body>
</ClientProviders>
</CookiesProvider>
</html>
);
}

View File

@ -1,4 +1,4 @@
export const THEMES = {
const THEMES = {
christmas: {
name: 'christmas',
month: 11,
@ -7,7 +7,7 @@ export const THEMES = {
},
};
export type Theme = keyof typeof THEMES | 'default';
type Theme = keyof typeof THEMES | 'default';
export const getAutoTheme = (): Theme => {
const date = new Date();

View File

@ -21,5 +21,3 @@ export const readFile = (path: string): string => {
export const readdirSync = (path: string): string[] => fs.readdirSync(path);
export const fileExists = (path: string): boolean => fs.existsSync(path);
export const unlinkFile = (path: string) => fs.promises.unlink(path);

View File

@ -12,14 +12,7 @@ export const isInstanceInsecure = () => {
const myHeaders = headers();
const ip = myHeaders.get('x-forwarded-host')?.split(':')[0] || '';
if (ipaddrjs.isValid(ip)) {
const range = ipaddrjs.parse(ip!).range();
if (range !== 'private' && range !== 'carrierGradeNat' && range !== 'loopback') {
return true;
}
} else if (ip !== 'localhost' && myHeaders.get('x-forwarded-proto') === 'http') {
return true;
}
return false;
const isPublicIp = ipaddrjs.isValid(ip) && !['private', 'carrierGradeNat', 'loopback'].includes(ipaddrjs.parse(ip).range());
const isHttpProtocol = ip !== 'localhost' && myHeaders.get('x-forwarded-proto') === 'http';
return isPublicIp || isHttpProtocol;
};