mirror of
https://github.com/pyrohost/pyrodactyl.git
synced 2026-04-06 04:01:58 +02:00
WE GOT VITE WORKING LETS FUCKING GOOOOOOOOOOOOO
This commit is contained in:
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"plugins": [
|
||||
"babel-plugin-macros",
|
||||
"styled-components",
|
||||
"@babel/proposal-class-properties",
|
||||
"@babel/proposal-object-rest-spread",
|
||||
"@babel/proposal-optional-chaining",
|
||||
"@babel/proposal-nullish-coalescing-operator",
|
||||
"@babel/syntax-dynamic-import"
|
||||
],
|
||||
"presets": ["@babel/typescript", ["@babel/react", { "runtime": "automatic" }]]
|
||||
}
|
||||
@@ -1,14 +1,18 @@
|
||||
/** @type {import('eslint').Linter.Config} */
|
||||
module.exports = {
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
ecmaVersion: 6,
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
overrides: [
|
||||
{
|
||||
parserOptions: {
|
||||
ecmaVersion: 6,
|
||||
ecmaFeatures: {
|
||||
jsx: true,
|
||||
},
|
||||
project: './tsconfig.json',
|
||||
tsconfigRootDir: './',
|
||||
},
|
||||
},
|
||||
project: './tsconfig.json',
|
||||
tsconfigRootDir: './',
|
||||
},
|
||||
],
|
||||
settings: {
|
||||
react: {
|
||||
pragma: 'React',
|
||||
@@ -23,11 +27,6 @@ module.exports = {
|
||||
browser: true,
|
||||
es6: true,
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.ts', '*.tsx'],
|
||||
},
|
||||
],
|
||||
plugins: ['react', 'react-hooks', 'prettier', '@typescript-eslint'],
|
||||
extends: [
|
||||
// 'standard',
|
||||
@@ -38,7 +37,8 @@ module.exports = {
|
||||
'plugin:jest-dom/recommended',
|
||||
],
|
||||
rules: {
|
||||
'prettier/prettier': 0,
|
||||
eqeqeq: 'error',
|
||||
'prettier/prettier': ['error', {}, { usePrettierrc: true }],
|
||||
// TypeScript can infer this significantly better than eslint ever can.
|
||||
'react/prop-types': 0,
|
||||
'react/display-name': 0,
|
||||
@@ -51,12 +51,7 @@ module.exports = {
|
||||
// @see https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/docs/rules/no-use-before-define.md#how-to-use
|
||||
'no-use-before-define': 0,
|
||||
'@typescript-eslint/no-use-before-define': 'warn',
|
||||
'@typescript-eslint/no-unused-vars': 0,
|
||||
'@typescript-eslint/ban-ts-comment': 0,
|
||||
},
|
||||
settings: {
|
||||
react: {
|
||||
version: 'detect',
|
||||
},
|
||||
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_', varsIgnorePattern: '^_' }],
|
||||
'@typescript-eslint/ban-ts-comment': ['error', { 'ts-expect-error': 'allow-with-description' }],
|
||||
},
|
||||
};
|
||||
@@ -7,19 +7,11 @@ use Pterodactyl\Services\Helpers\AssetHashService;
|
||||
|
||||
class AssetComposer
|
||||
{
|
||||
/**
|
||||
* AssetComposer constructor.
|
||||
*/
|
||||
public function __construct(private AssetHashService $assetHashService)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Provide access to the asset service in the views.
|
||||
*/
|
||||
public function compose(View $view): void
|
||||
{
|
||||
$view->with('asset', $this->assetHashService);
|
||||
$view->with('siteConfiguration', [
|
||||
'name' => config('app.name') ?? 'Pterodactyl',
|
||||
'locale' => config('app.locale') ?? 'en',
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace Pterodactyl\Services\Helpers;
|
||||
|
||||
use Illuminate\Support\Arr;
|
||||
use Illuminate\Filesystem\FilesystemManager;
|
||||
use Illuminate\Contracts\Filesystem\Filesystem;
|
||||
use Pterodactyl\Exceptions\ManifestDoesNotExistException;
|
||||
|
||||
class AssetHashService
|
||||
{
|
||||
/**
|
||||
* Location of the manifest file generated by gulp.
|
||||
*/
|
||||
public const MANIFEST_PATH = './assets/manifest.json';
|
||||
|
||||
private Filesystem $filesystem;
|
||||
|
||||
protected static mixed $manifest = null;
|
||||
|
||||
/**
|
||||
* AssetHashService constructor.
|
||||
*/
|
||||
public function __construct(FilesystemManager $filesystem)
|
||||
{
|
||||
$this->filesystem = $filesystem->createLocalDriver(['root' => public_path()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify a URL to append the asset hash.
|
||||
*/
|
||||
public function url(string $resource): string
|
||||
{
|
||||
$file = last(explode('/', $resource));
|
||||
$data = Arr::get($this->manifest(), $file) ?? $file;
|
||||
|
||||
return str_replace($file, Arr::get($data, 'src') ?? $file, $resource);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the data integrity hash for a resource.
|
||||
*/
|
||||
public function integrity(string $resource): string
|
||||
{
|
||||
$file = last(explode('/', $resource));
|
||||
$data = array_get($this->manifest(), $file, $file);
|
||||
|
||||
return Arr::get($data, 'integrity') ?? '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a built CSS import using the provided URL.
|
||||
*/
|
||||
public function css(string $resource): string
|
||||
{
|
||||
$attributes = [
|
||||
'href' => $this->url($resource),
|
||||
'rel' => 'stylesheet preload',
|
||||
'as' => 'style',
|
||||
'crossorigin' => 'anonymous',
|
||||
'referrerpolicy' => 'no-referrer',
|
||||
];
|
||||
|
||||
if (config('pterodactyl.assets.use_hash')) {
|
||||
$attributes['integrity'] = $this->integrity($resource);
|
||||
}
|
||||
|
||||
$output = '<link';
|
||||
foreach ($attributes as $key => $value) {
|
||||
$output .= " $key=\"$value\"";
|
||||
}
|
||||
|
||||
return $output . '>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a built JS import using the provided URL.
|
||||
*/
|
||||
public function js(string $resource): string
|
||||
{
|
||||
$attributes = [
|
||||
'src' => $this->url($resource),
|
||||
'crossorigin' => 'anonymous',
|
||||
];
|
||||
|
||||
if (config('pterodactyl.assets.use_hash')) {
|
||||
$attributes['integrity'] = $this->integrity($resource);
|
||||
}
|
||||
|
||||
$output = '<script';
|
||||
foreach ($attributes as $key => $value) {
|
||||
$output .= " $key=\"$value\"";
|
||||
}
|
||||
|
||||
return $output . '></script>';
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the asset manifest and store it in the cache for quicker lookups.
|
||||
*/
|
||||
protected function manifest(): array
|
||||
{
|
||||
if (static::$manifest === null) {
|
||||
self::$manifest = json_decode(
|
||||
$this->filesystem->get(self::MANIFEST_PATH),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
$manifest = static::$manifest;
|
||||
if ($manifest === null) {
|
||||
throw new ManifestDoesNotExistException();
|
||||
}
|
||||
|
||||
return $manifest;
|
||||
}
|
||||
}
|
||||
@@ -6,7 +6,7 @@ module.exports = {
|
||||
preset: 'ts-jest',
|
||||
globals: {
|
||||
'ts-jest': {
|
||||
isolatedModules: true,
|
||||
isolatedModules: true,
|
||||
},
|
||||
},
|
||||
moduleFileExtensions: ['js', 'ts', 'tsx', 'd.ts', 'json', 'node'],
|
||||
839
package-lock.json
generated
839
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
17
package.json
17
package.json
@@ -1,13 +1,15 @@
|
||||
{
|
||||
"name": "pterodactyl-panel",
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
"node": ">=20.0"
|
||||
},
|
||||
"type": "module",
|
||||
"dependencies": {
|
||||
"@headlessui/react": "^1.6.4",
|
||||
"@preact/signals-react": "^1.2.1",
|
||||
"@tailwindcss/forms": "^0.5.7",
|
||||
"@tailwindcss/line-clamp": "^0.4.4",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"axios": "^0.27.2",
|
||||
"browserslist": "^4.23.0",
|
||||
"chart.js": "^3.8.0",
|
||||
@@ -22,6 +24,7 @@
|
||||
"events": "^3.0.0",
|
||||
"formik": "^2.4.5",
|
||||
"framer-motion": "^11.0.8",
|
||||
"laravel-vite-plugin": "^1.0.2",
|
||||
"pathe": "^1.1.2",
|
||||
"qrcode.react": "^1.0.1",
|
||||
"react": "^18.2.0",
|
||||
@@ -38,6 +41,7 @@
|
||||
"swr": "^2.2.5",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"uuid": "^8.3.2",
|
||||
"vite": "^5.1.4",
|
||||
"xterm": "^5.3.0",
|
||||
"xterm-addon-fit": "^0.8.0",
|
||||
"xterm-addon-search": "^0.13.0",
|
||||
@@ -67,7 +71,7 @@
|
||||
"@types/debounce": "^1.2.0",
|
||||
"@types/events": "^3.0.0",
|
||||
"@types/jest": "^28.1.3",
|
||||
"@types/node": "^14.11.10",
|
||||
"@types/node": "^20.11.24",
|
||||
"@types/qrcode.react": "^1.0.1",
|
||||
"@types/react": "^17.0.76",
|
||||
"@types/react-copy-to-clipboard": "^4.3.0",
|
||||
@@ -124,12 +128,8 @@
|
||||
"clean": "cd public/assets && find . \\( -name \"*.js\" -o -name \"*.map\" \\) -type f -delete",
|
||||
"test": "jest",
|
||||
"lint": "eslint ./resources/scripts/**/*.{ts,tsx} --ext .ts,.tsx",
|
||||
"//watch": "I set node_env to production because watch does not work otherwise. Too bad!",
|
||||
"watch": "cross-env NODE_ENV=production NODE_OPTIONS=--openssl-legacy-provider ./node_modules/.bin/webpack --watch --progress",
|
||||
"build": "cross-env NODE_ENV=development NODE_OPTIONS=--openssl-legacy-provider ./node_modules/.bin/webpack --progress",
|
||||
"build:fast": "cross-env NODE_ENV=development NODE_OPTIONS=--openssl-legacy-provider TYPE_CHECKING=false ./node_modules/.bin/webpack --progress && echo \"\n[!] Type checking was disabled for this build, this may result in runtime errors.\n\"",
|
||||
"build:production": "cross-env NODE_ENV=production NODE_OPTIONS=--openssl-legacy-provider ./node_modules/.bin/webpack --mode production",
|
||||
"serve": "npm run clean && cross-env WEBPACK_PUBLIC_PATH=/webpack@hmr/ NODE_ENV=development webpack-dev-server --host 0.0.0.0 --port 8080 --public https://pterodactyl.test --hot"
|
||||
"dev": "vite",
|
||||
"build": "vite build"
|
||||
},
|
||||
"browserslist": [
|
||||
"> 0.5%",
|
||||
@@ -139,6 +139,7 @@
|
||||
],
|
||||
"babelMacros": {
|
||||
"twin": {
|
||||
"config": "tailwind.config.cjs",
|
||||
"preset": "styled-components"
|
||||
},
|
||||
"styledComponents": {
|
||||
|
||||
@@ -86,6 +86,7 @@ export default () => {
|
||||
}}
|
||||
/>
|
||||
<SubNavigation>
|
||||
<div>hi 2</div>
|
||||
<div className='flex flex-row items-center justify-between h-8'>
|
||||
<Link to={'/'} className='flex shrink-0 h-full w-fit'>
|
||||
<Logo />
|
||||
|
||||
@@ -32,6 +32,9 @@
|
||||
@yield('assets')
|
||||
|
||||
@include('layouts.scripts')
|
||||
|
||||
@viteReactRefresh
|
||||
@vite('resources/scripts/index.tsx')
|
||||
</head>
|
||||
<body data-pyro-body class="{{ $css['body'] ?? 'bg-zinc-50' }}">
|
||||
@section('content')
|
||||
@@ -39,8 +42,5 @@
|
||||
@yield('container')
|
||||
@yield('below-container')
|
||||
@show
|
||||
@section('scripts')
|
||||
{!! $asset->js('main.js') !!}
|
||||
@show
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -45,6 +45,6 @@
|
||||
"stripInternal": true,
|
||||
"useDefineForClassFields": true
|
||||
},
|
||||
"include": ["./resources/scripts/**/*"],
|
||||
"include": ["./resources/scripts/**/*", "vite.config.ts"],
|
||||
"exclude": ["node_modules"]
|
||||
}
|
||||
|
||||
58
vite.config.ts
Normal file
58
vite.config.ts
Normal file
@@ -0,0 +1,58 @@
|
||||
import react from '@vitejs/plugin-react';
|
||||
import laravel from 'laravel-vite-plugin';
|
||||
import { dirname, resolve } from 'pathe';
|
||||
import { fileURLToPath } from 'node:url';
|
||||
import { defineConfig } from 'vite';
|
||||
|
||||
export default defineConfig({
|
||||
build: {
|
||||
assetsInlineLimit: 0,
|
||||
emptyOutDir: true,
|
||||
// we need to do this because otherwise it will
|
||||
// generate in .vite/manifest.json, while laravel
|
||||
// looks in public/build/manifest.json
|
||||
manifest: 'manifest.json',
|
||||
outDir: 'public/build',
|
||||
|
||||
rollupOptions: {
|
||||
input: 'resources/scripts/index.tsx',
|
||||
},
|
||||
},
|
||||
|
||||
define: {
|
||||
'process.env': {},
|
||||
'process.platform': null,
|
||||
'process.version': null,
|
||||
'process.versions': null,
|
||||
},
|
||||
|
||||
plugins: [
|
||||
laravel('resources/scripts/index.tsx'),
|
||||
react({
|
||||
babel: {
|
||||
plugins: ['babel-plugin-macros', 'babel-plugin-styled-components'],
|
||||
},
|
||||
}),
|
||||
],
|
||||
|
||||
resolve: {
|
||||
alias: {
|
||||
'@': resolve(dirname(fileURLToPath(import.meta.url)), 'resources', 'scripts'),
|
||||
'@definitions': resolve(
|
||||
dirname(fileURLToPath(import.meta.url)),
|
||||
'resources',
|
||||
'scripts',
|
||||
'api',
|
||||
'definitions'
|
||||
),
|
||||
'@feature': resolve(
|
||||
dirname(fileURLToPath(import.meta.url)),
|
||||
'resources',
|
||||
'scripts',
|
||||
'components',
|
||||
'server',
|
||||
'features'
|
||||
),
|
||||
},
|
||||
},
|
||||
});
|
||||
@@ -1,169 +0,0 @@
|
||||
const path = require('path');
|
||||
const webpack = require('webpack');
|
||||
const AssetsManifestPlugin = require('webpack-assets-manifest');
|
||||
const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
|
||||
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin;
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
|
||||
const isProduction = process.env.NODE_ENV === 'production';
|
||||
const typeChecking = process.env.TYPE_CHECKING !== 'false';
|
||||
|
||||
module.exports = {
|
||||
resolve: {
|
||||
extensions: ['.js', '.jsx', '.json', '.ts', '.tsx'],
|
||||
fallback: {
|
||||
fs: require.resolve('fs'),
|
||||
os: require.resolve('os-browserify/browser'),
|
||||
path: require.resolve('path-browserify'),
|
||||
},
|
||||
},
|
||||
cache: true,
|
||||
target: 'web',
|
||||
mode: isProduction ? 'production' : 'development',
|
||||
devtool: isProduction ? false : process.env.DEVTOOL || 'eval-source-map',
|
||||
performance: {
|
||||
hints: false,
|
||||
},
|
||||
entry: ['./resources/scripts/index.tsx'],
|
||||
output: {
|
||||
path: path.join(__dirname, '/public/assets'),
|
||||
filename: 'bundle.js', // Simplify filename for development
|
||||
publicPath: process.env.WEBPACK_PUBLIC_PATH || '/assets/',
|
||||
crossOriginLoading: 'anonymous',
|
||||
pathinfo: false,
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.tsx?$/,
|
||||
exclude: /node_modules|\.spec\.tsx?$/,
|
||||
use: {
|
||||
loader: 'babel-loader',
|
||||
options: {
|
||||
cacheDirectory: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
// Doesn't work sadly cause our packages need to be polyfilled
|
||||
// and webpack doesn't feel like doing that ???
|
||||
// {
|
||||
// // Match `.js`, `.jsx`, `.ts` or `.tsx` files
|
||||
// test: /\.[jt]sx?$/,
|
||||
// exclude: /node_modules|\.spec\.tsx?$/,
|
||||
// loader: 'esbuild-loader',
|
||||
// options: {
|
||||
// // JavaScript version to compile to
|
||||
// target: 'es2015',
|
||||
// },
|
||||
// },
|
||||
|
||||
// Why do we need to transpile node_modules? Removing this doesn't
|
||||
// break builds for me, but I'll keep it just in case. Should be
|
||||
// faster with swc
|
||||
{
|
||||
test: /\.mjs$/,
|
||||
include: /node_modules/,
|
||||
type: 'javascript/auto',
|
||||
// fails on production, works on dev
|
||||
// use: {
|
||||
// loader: 'swc-loader',
|
||||
// options: {
|
||||
// parseMap: true,
|
||||
// },
|
||||
// },
|
||||
},
|
||||
{
|
||||
test: /\.css$/,
|
||||
use: ['style-loader', 'css-loader', 'postcss-loader'], // Simplified CSS loader configuration
|
||||
},
|
||||
{
|
||||
test: /\.(png|jp(e?)g|gif)$/,
|
||||
loader: 'file-loader',
|
||||
options: {
|
||||
name: 'images/[name].[hash:8].[ext]',
|
||||
},
|
||||
},
|
||||
{
|
||||
test: /\.svg$/,
|
||||
loader: 'svg-url-loader',
|
||||
},
|
||||
],
|
||||
},
|
||||
resolve: {
|
||||
extensions: ['.ts', '.tsx', '.js', '.json'],
|
||||
alias: {
|
||||
'@': path.join(__dirname, '/resources/scripts'),
|
||||
'@definitions': path.join(__dirname, '/resources/scripts/api/definitions'),
|
||||
'@feature': path.join(__dirname, '/resources/scripts/components/server/features'),
|
||||
},
|
||||
symlinks: false,
|
||||
},
|
||||
externals: {
|
||||
moment: 'moment',
|
||||
},
|
||||
plugins: [
|
||||
new webpack.EnvironmentPlugin({
|
||||
NODE_ENV: isProduction ? 'production' : 'development',
|
||||
DEBUG: isProduction ? 'false' : 'true',
|
||||
WEBPACK_BUILD_HASH: Date.now().toString(16),
|
||||
}),
|
||||
|
||||
new AssetsManifestPlugin({ writeToDisk: true, publicPath: true, integrity: true, integrityHashes: ['sha384'] }),
|
||||
|
||||
typeChecking
|
||||
? new ForkTsCheckerWebpackPlugin({
|
||||
typescript: {
|
||||
mode: 'write-references',
|
||||
diagnosticOptions: {
|
||||
semantic: true,
|
||||
syntactic: true,
|
||||
},
|
||||
},
|
||||
eslint: {
|
||||
files: `${path.join(__dirname, '/resources/scripts')}/**/*.{ts,tsx}`,
|
||||
},
|
||||
})
|
||||
: null,
|
||||
|
||||
process.env.ANALYZE_BUNDLE
|
||||
? new BundleAnalyzerPlugin({
|
||||
analyzerHost: '0.0.0.0',
|
||||
analyzerPort: 8081,
|
||||
})
|
||||
: null,
|
||||
].filter((p) => p),
|
||||
optimization: {
|
||||
usedExports: isProduction,
|
||||
sideEffects: isProduction,
|
||||
removeEmptyChunks: isProduction,
|
||||
mergeDuplicateChunks: isProduction,
|
||||
providedExports: isProduction,
|
||||
concatenateModules: isProduction,
|
||||
minimize: isProduction,
|
||||
minimizer: [
|
||||
new TerserPlugin({
|
||||
extractComments: false,
|
||||
terserOptions: {
|
||||
compress: {
|
||||
drop_console: true,
|
||||
},
|
||||
},
|
||||
}),
|
||||
],
|
||||
},
|
||||
watchOptions: {
|
||||
poll: 1000,
|
||||
ignored: /node_modules/,
|
||||
},
|
||||
devServer: {
|
||||
hot: true,
|
||||
port: 3000,
|
||||
compress: true,
|
||||
contentBase: path.join(__dirname, '/public'),
|
||||
publicPath: process.env.WEBPACK_PUBLIC_PATH || '/assets/',
|
||||
allowedHosts: ['.pterodactyl.test'],
|
||||
headers: {
|
||||
'Access-Control-Allow-Origin': '*',
|
||||
},
|
||||
},
|
||||
};
|
||||
Reference in New Issue
Block a user