Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
e3467d1
refactor: standardize cookie names using shared constants
tabarra Mar 8, 2025
ad056f2
tweak(panel): handle removeChild error in dev mode by auto-reloading …
tabarra Mar 8, 2025
72fdd0b
feat(panel): added theme-aware terminal colors and styling
tabarra Mar 9, 2025
c731f6b
feat(panel): add live console persistent options popover
tabarra Mar 9, 2025
2d24d8b
chore: added missing dev script
tabarra Mar 9, 2025
1c4e446
tweak: healedPlayer -> playerHealed
mardev-xyz Mar 9, 2025
60309de
Merge pull request #1039 from mardev-xyz/mardev-xyz-patch-1
tabarra Mar 10, 2025
9b92cd5
style: fixed padding on WarningBar
tabarra Mar 15, 2025
83cdd5f
feat(panel): add 3xl breakpoint and fixed dashboard layout overflow
tabarra Mar 15, 2025
11624cf
fix(core): sort actions query result
tabarra Mar 16, 2025
35cafe4
tweak(core): only print db optimization if it happened
tabarra Mar 16, 2025
5e8a6bb
tweak: updated copyright notice
tabarra May 26, 2025
77f2cb7
fix: controls for resources containing apostrophe (#1053)
tabarra May 26, 2025
c657725
tweak(panel): improve error handling for outdated browsers
tabarra Jun 2, 2025
18ac963
tweak(web): updated recipe index url
tabarra Jun 2, 2025
10a5656
tweak(adverts): updated hosting partner list
tabarra Jun 20, 2025
f8ef970
feat(core): highlight invalid chars on path error message
tabarra Jun 22, 2025
cd0d08d
fix(core): don't set tty title for hosting providers
tabarra Jun 24, 2025
e51c92b
test(panel): disable failing test for now
tabarra Jun 28, 2025
34c4fca
feat(menu): suggest respawning the last spawned vehicle
tabarra Jun 28, 2025
7391ab3
feat: added option to delete specific player ids
tabarra Jun 28, 2025
c7bc66b
wip: small stuff + docs
tabarra Jun 28, 2025
1b3ac02
feat(panel/liveConsole): print empty lines when pressing enter with e…
tabarra Jun 28, 2025
f6cf8e8
fix(panel): fixed advert images for nui iframe
tabarra Jun 28, 2025
c057f4e
tweak(panel/playerModal): refined delete ids action feedback
tabarra Jun 29, 2025
acd23d9
refactor(panel): player & action modal components cleanup
tabarra Jun 29, 2025
a4cdc6b
wip: small changes
tabarra Jul 5, 2025
949eebd
refactor(panel): centralize localStorage keys for better organization
tabarra Jul 25, 2025
0b092df
feat(panel/CardContentOverlay): enhance loading state handling and ad…
tabarra Jul 25, 2025
598a3ae
refactor: migrated diagnostics page and temp disabled reporting
tabarra Jul 25, 2025
1462478
wip: small changes
tabarra Jul 25, 2025
b6544a4
feat(web/admins): added identifiers to admins table
tabarra Jul 26, 2025
9e73fd4
wip: small stuff
tabarra Jul 26, 2025
a0f0a5a
feat(core): added advanced command `printFxResourcesBootLog`
tabarra Jul 26, 2025
657594d
wip: small stuff
tabarra Jul 26, 2025
a3d5c55
refactor: rewrote the advanced cmds page
tabarra Jul 27, 2025
b65c8b1
wip: small changes
tabarra Jul 27, 2025
530830c
feat: added verbose logging for admin manager actions
tabarra Jul 27, 2025
8ec3bd0
fix(core): fixed bug which made impossible to remove a provider id + …
tabarra Jul 27, 2025
15c1769
feat: added verbose logging for admin add action
tabarra Jul 27, 2025
f69b024
wip: improved panel timeout error handling + small stuff
tabarra Jul 28, 2025
b4204f5
tweak(panel/playerDrops): improved timeline chart cursor behavior
tabarra Jul 29, 2025
f3e30f6
fix(core): updated server log ws room to use the new permission
tabarra Nov 26, 2025
d192eff
fix(web): resources page stop button not working
tabarra Dec 5, 2025
77987f3
tweak: improved discord bot dangerous perms warning message
tabarra Dec 6, 2025
e2a5c92
tweak: highlight every non-ascii char in path error message
tabarra Dec 15, 2025
6a591e0
feat(core): added details to "changing own ids" action log msg
tabarra Dec 19, 2025
243f128
tweak: minor stuff
tabarra Dec 24, 2025
219d547
tweak: renamed the perms for removing player ids
tabarra Dec 26, 2025
abee64d
chore(panel): created new ui showcase test page
tabarra Dec 27, 2025
a50ea2f
tweak(panel/playerDrops): sorting env changes as DESC
tabarra Dec 31, 2025
a1542e1
tweak(panel/playerDrops): improved timeline day start rounding
tabarra Dec 31, 2025
ad39a7d
tweak(panel/playerDrops): small changes - read desc
tabarra Dec 31, 2025
6017647
fix(panel/playerDrops): fixed timeline window start calc
tabarra Jan 22, 2026
9b5c4b6
wip: small stuff
tabarra Jan 27, 2026
065e319
chore: added git hook to block pushing private branches to origin
tabarra Jan 27, 2026
e7d2006
Merge branch 'feat/player-drops-page-improvements' into develop
tabarra Jan 27, 2026
26c4971
fix(shared): enable proper ESM import
Frowmza Sep 20, 2025
236d2c7
style(panel): removed forced TxAnchor margin
tabarra Jan 29, 2026
46fcbc4
wip: moved components + fixed theme toggle alignment
tabarra Jan 31, 2026
35e173a
test(panel): fixed outdated live console utils test
tabarra Jan 31, 2026
249757b
fix: hardened legacy template rendering and script constants
tabarra Mar 5, 2026
66a23af
feat: improved printClockInfo advanced command
tabarra May 28, 2026
0342f8a
feat(web): improved rendering of markdown and json blocks
tabarra May 28, 2026
9ea5281
chore: small fixes and tweaks
tabarra May 28, 2026
45ae29f
wip: renamed whitelist to allowlist in panel & web
tabarra May 31, 2026
a94cf7a
feat(panel): added soft char limit to autosize textarea
tabarra May 31, 2026
b7497cb
feat(panel): improved settings components
tabarra May 31, 2026
bdb55a9
feat: added external allowlist option
tabarra May 31, 2026
92071ed
Merge branch 'feat/allowlist' into develop
tabarra Jun 1, 2026
f331594
wip: small changes
tabarra Jun 1, 2026
931705f
chore: updated styling for connection rejection wrapper to match new …
tabarra Jun 1, 2026
f6ffd33
Make txAdmin a PWA
Cocodrulo Aug 22, 2025
474fe57
Change description, icons and theme color for PWA
Cocodrulo Aug 23, 2025
2df0260
chore: update translations
tabarra Jun 3, 2026
372e915
ci: remove pr branch enforcement
tabarra Jun 3, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 0 additions & 17 deletions .github/workflows/locale-pull-request.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,23 +12,6 @@ jobs:
pull-requests: write

steps:
- name: Enforce base branch
uses: actions/github-script@v7
with:
script: |
// Get the pull request
const pull_request = await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number
});

// Check if the base branch is 'main' or 'master'
if (pull_request.data.base.ref === 'main' || pull_request.data.base.ref === 'master') {
console.error('Pull request is targeting the main branch. Please target the develop branch instead.');
process.exit(1);
}

- name: Use Node.js 22
uses: actions/setup-node@v4
with:
Expand Down
3 changes: 3 additions & 0 deletions .husky/pre-push
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
#!/usr/bin/env bash
set -euo pipefail
exec bun run "$(dirname "$0")/pre-push.ts" "$@"
51 changes: 51 additions & 0 deletions .husky/pre-push.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#!/usr/bin/env bun
import { readFileSync } from 'node:fs';

//MARK: Configs
const protectedBranchPrefixRegex = /^(experiments?|mock(up)?s?|private)\//;
const allowedRemoteName = 'git.fivem.net';

//MARK: Parsing push data
const remoteName = process.argv[2] ?? '';
const remoteUrl = process.argv[3] ?? '';

//No restrictions on the allowed remote
if (remoteName === allowedRemoteName) {
process.exit(0);
}

// Read refs being pushed from stdin.
const stdin = readFileSync(0, 'utf8');
const lines = stdin.split('\n').map((l) => l.trim()).filter(Boolean);

const blocked: string[] = [];
for (const line of lines) {
//Parse line
const parts = line.split(/\s+/);
if (parts.length < 4) continue;
const [localRef, localSha, remoteRef, remoteSha] = parts;

// Check branches
if (!localRef.startsWith('refs/heads/')) continue;
const branch = localRef.slice('refs/heads/'.length);
if (protectedBranchPrefixRegex.test(branch)) {
blocked.push(branch);
}
}

//MARK: Output
if (!blocked.length) {
process.exit(0);
}

//Oh noooo :(
const msg = [
`❌ Push blocked: these branches may only be pushed to ${allowedRemoteName}.`,
`Remote: ${remoteName} (${remoteUrl})`,
`Blocked branches:`,
...blocked.map((b) => ` - ${b}`),
``,
`Fix: push to ${allowedRemoteName}.`
].join('\n');
process.stderr.write(msg);
process.exit(1);
2 changes: 1 addition & 1 deletion LICENSE
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
MIT License

Copyright (c) 2019-2025 André Tabarra <maintainer@txadmin.gg>
Copyright (c) 2019-2025 Take-Two Interactive Software, Inc.

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
Expand Down
1 change: 1 addition & 0 deletions commitlint.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
'type-enum': [2, 'always', types],
// 'body-max-line-length': [0, 'always', 100],
},
};
7 changes: 2 additions & 5 deletions core/boot/startReadyWatcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import { chalkInversePad } from '@lib/misc';
const console = consoleFactory();


const getPublicIp = async () => {
export const getPublicIp = async () => {
const zIpValidator = z.string().ip();
const reqOptions = {
timeout: { request: 2000 },
Expand Down Expand Up @@ -41,16 +41,13 @@ const getPublicIp = async () => {
const getOSMessage = async () => {
const serverMessage = [
`To be able to access txAdmin from the internet open port ${txHostConfig.txaPort}`,
'on your OS Firewall as well as in the hosting company.',
'on your OS Firewall as well as in the hosting provider.',
];
const winWorkstationMessage = [
'[!] Home-hosting fxserver is not recommended [!]',
'You need to open the fxserver port (usually 30120) on Windows Firewall',
'and set up port forwarding on your router so other players can access it.',
];
if (txEnv.displayAds) {
winWorkstationMessage.push('We recommend renting a server from ' + chalk.inverse(' https://zap-hosting.com/txAdmin ') + '.');
}

//FIXME: use si.osInfo() instead
const distro = await getOsDistro();
Expand Down
63 changes: 32 additions & 31 deletions core/globalData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ import { getHostVars, hostEnvVarSchemas } from './boot/getHostVars';
import { getZapVars } from './boot/getZapVars';
import { z, ZodSchema } from 'zod';
import { fromZodError } from 'zod-validation-error';
import defaultAds from '../dynamicAds2.json';
import consts from '@shared/consts';
import chalk from 'chalk';
const console = consoleFactory();


Expand Down Expand Up @@ -209,15 +209,18 @@ if (dataPathVar) {
//NOTE: Non-ASCII in one of those paths (don't know which) will make NodeJS crash due to a bug in v8 (or something)
// when running localization methods like Date.toLocaleString().
// There was also an issue with the slash() lib and with the +exec on FXServer
const nonASCIIRegex = /[^\x00-\x80]+/;
const nonASCIIRegex = /[^\x00-\x80]+/g;
const colorNonAscii = (x: string) => chalk.black.bgGreenBright(
x.replaceAll(nonASCIIRegex, (m) => chalk.bgRedBright(m))
);
if (nonASCIIRegex.test(fxsPath) || nonASCIIRegex.test(dataPath)) {
fatalError.GlobalData(7, [
'Due to environmental restrictions, your paths CANNOT contain non-ASCII characters.',
'Example of non-ASCII characters: çâýå, ρέθ, ñäé, ēļæ, глж, เซิร์, 警告.',
'Please make sure FXServer is not in a path contaning those characters.',
`If on windows, we suggest you moving the artifact to "C:/fivemserver/${fxsVersion}/".`,
['FXServer path', fxsPath],
['txData path', dataPath],
'FXServer path: ' + colorNonAscii(fxsPath),
'txData path: ' + colorNonAscii(dataPath),
]);
}

Expand Down Expand Up @@ -471,36 +474,33 @@ if (ignoreDeprecatedConfigs) {

const isPterodactyl = !isWindows && process.env?.TXADMIN_ENABLE === '1';
const isZapHosting = providerName === 'ZAP-Hosting';
const setConsoleTitle = !(isPterodactyl || isZapHosting || providerName); //assume not a terminal

//Quick config to disable ads
const displayAds = process.env?.TXHOST_TMP_HIDE_ADS !== 'true' || isPterodactyl || isZapHosting;
const adSchema = z.object({
img: z.string(),
url: z.string(),
}).nullable();
const adsDataSchema = z.object({
login: adSchema,
main: adSchema,
});
let adsData: z.infer<typeof adsDataSchema> = {
login: null,
main: null,
};
if (displayAds) {
try {
adsData = adsDataSchema.parse(defaultAds);
} catch (error) {
console.error('Failed to load ads data.', error);
}
}

//FXServer Display Version
let fxsVersionTag = fxsVersion.toString();
if (fxsVerParsed.branch && fxsVerParsed.branch !== 'master') {
fxsVersionTag += '-ft';
}
if (isZapHosting) {
fxsVersionTag += '/ZAP';

let providerTag = '';
const partnerPrefixes = {
'gportal': 'GPor',
'nitrado': 'Nitr',
'nodecraft': 'NoCr',
'shockbyte': 'ShBy',
'xrealm': 'XRea',
'zaphosting': 'ZapH',
} as { [key: string]: string };
if (providerName) {
const cleanName = providerName.toLowerCase().replace(/[^a-z0-9]+/g, '');
if (cleanName in partnerPrefixes) {
providerTag = partnerPrefixes[cleanName];
}
}

if (providerTag) {
fxsVersionTag += `/${providerTag}`;
} else if (isPterodactyl) {
fxsVersionTag += '/Ptero';
} else if (isWindows && fxsVerParsed.platform === 'windows') {
Expand All @@ -520,10 +520,11 @@ export const txDevEnv = Object.freeze(_txDevEnv);
export const txEnv = Object.freeze({
//Calculated
isWindows,
isPterodactyl, //TODO: remove, used only in HB Data
isZapHosting, //TODO: remove, used only in HB Data and authLogic to disable src check
displayAds,
adsData,
setConsoleTitle,

//TODO: remove, used only in diagnostics (HB Data + page)
isPterodactyl,
isZapHosting, //NOTE: This one is also used in authLogic to disable src check

//Natives
fxsVersionTag,
Expand Down
3 changes: 1 addition & 2 deletions core/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//NOTE: must be imported first to setup the environment
import { txEnv, txHostConfig } from './globalData';
import consoleFactory, { setTTYTitle } from '@lib/console';
import consoleFactory from '@lib/console';

//Can be imported after
import fs from 'node:fs';
Expand All @@ -16,7 +16,6 @@ const console = consoleFactory();
try {
process.title = 'txAdmin'; //doesn't work for now
setupProcessHandlers();
setTTYTitle();
checkPreRelease();
} catch (error) {
fatalError.Boot(0, 'Failed early process setup.', error);
Expand Down
Loading
Loading