Merge branch 'dev' into fix/define-files-in-eslint

This commit is contained in:
Thijs van Loef 2025-06-09 22:36:56 +02:00 committed by GitHub
commit c7018e92b0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
10 changed files with 2999 additions and 367 deletions

View file

@ -13,10 +13,6 @@ updates:
dependency-type: "development" dependency-type: "development"
update-types: update-types:
- "minor" - "minor"
dev-major-updates:
dependency-type: "development"
update-types:
- "major"
prod-patch-updates: prod-patch-updates:
dependency-type: "production" dependency-type: "production"
update-types: update-types:
@ -25,10 +21,6 @@ updates:
dependency-type: "production" dependency-type: "production"
update-types: update-types:
- "minor" - "minor"
prod-major-updates:
dependency-type: "production"
update-types:
- "major"
- package-ecosystem: "docker" - package-ecosystem: "docker"
directory: "/" directory: "/"
@ -41,6 +33,3 @@ updates:
minor-updates: minor-updates:
update-types: update-types:
- "minor" - "minor"
major-updates:
update-types:
- "major"

3249
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -104,7 +104,7 @@
"winston": "3.17.0", "winston": "3.17.0",
"winston-daily-rotate-file": "5.0.0", "winston-daily-rotate-file": "5.0.0",
"ws": "8.18.2", "ws": "8.18.2",
"zod": "3.25.46", "zod": "3.25.56",
"zod-validation-error": "3.4.1" "zod-validation-error": "3.4.1"
}, },
"devDependencies": { "devDependencies": {
@ -112,8 +112,8 @@
"@esbuild-plugins/tsconfig-paths": "0.1.2", "@esbuild-plugins/tsconfig-paths": "0.1.2",
"@tailwindcss/postcss": "^4.1.8", "@tailwindcss/postcss": "^4.1.8",
"@types/better-sqlite3": "7.6.12", "@types/better-sqlite3": "7.6.12",
"@types/cookie-parser": "1.4.8", "@types/cookie-parser": "1.4.9",
"@types/cors": "2.8.18", "@types/cors": "2.8.19",
"@types/crypto-js": "^4.2.2", "@types/crypto-js": "^4.2.2",
"@types/express": "5.0.0", "@types/express": "5.0.0",
"@types/jmespath": "^0.15.2", "@types/jmespath": "^0.15.2",
@ -122,7 +122,7 @@
"@types/node": "^22", "@types/node": "^22",
"@types/nodemailer": "6.4.17", "@types/nodemailer": "6.4.17",
"@types/react": "19.1.6", "@types/react": "19.1.6",
"@types/react-dom": "19.1.5", "@types/react-dom": "19.1.6",
"@types/semver": "7.7.0", "@types/semver": "7.7.0",
"@types/swagger-ui-express": "^4.1.8", "@types/swagger-ui-express": "^4.1.8",
"@types/ws": "8.18.1", "@types/ws": "8.18.1",
@ -131,7 +131,7 @@
"esbuild": "0.25.5", "esbuild": "0.25.5",
"esbuild-node-externals": "1.18.0", "esbuild-node-externals": "1.18.0",
"postcss": "^8", "postcss": "^8",
"react-email": "4.0.15", "react-email": "4.0.16",
"tailwindcss": "^4.1.4", "tailwindcss": "^4.1.4",
"tsc-alias": "1.8.16", "tsc-alias": "1.8.16",
"tsx": "4.19.4", "tsx": "4.19.4",

View file

@ -2,7 +2,7 @@ import path from "path";
import { fileURLToPath } from "url"; import { fileURLToPath } from "url";
// This is a placeholder value replaced by the build process // This is a placeholder value replaced by the build process
export const APP_VERSION = "1.5.0"; export const APP_VERSION = "1.5.1";
export const __FILENAME = fileURLToPath(import.meta.url); export const __FILENAME = fileURLToPath(import.meta.url);
export const __DIRNAME = path.dirname(__FILENAME); export const __DIRNAME = path.dirname(__FILENAME);

View file

@ -27,6 +27,7 @@ import { formatAxiosError } from "@app/lib/api";
import { createApiClient } from "@app/lib/api"; import { createApiClient } from "@app/lib/api";
import { useEnvContext } from "@app/hooks/useEnvContext"; import { useEnvContext } from "@app/hooks/useEnvContext";
import CreateSiteFormModal from "./CreateSiteModal"; import CreateSiteFormModal from "./CreateSiteModal";
import { parseDataSize } from '@app/lib/dataSize';
export type SiteRow = { export type SiteRow = {
id: number; id: number;
@ -197,7 +198,9 @@ export default function SitesTable({ sites, orgId }: SitesTableProps) {
<ArrowUpDown className="ml-2 h-4 w-4" /> <ArrowUpDown className="ml-2 h-4 w-4" />
</Button> </Button>
); );
} },
sortingFn: (rowA, rowB) =>
parseDataSize(rowA.original.mbIn) - parseDataSize(rowB.original.mbIn)
}, },
{ {
accessorKey: "mbOut", accessorKey: "mbOut",
@ -213,7 +216,9 @@ export default function SitesTable({ sites, orgId }: SitesTableProps) {
<ArrowUpDown className="ml-2 h-4 w-4" /> <ArrowUpDown className="ml-2 h-4 w-4" />
</Button> </Button>
); );
} },
sortingFn: (rowA, rowB) =>
parseDataSize(rowA.original.mbOut) - parseDataSize(rowB.original.mbOut),
}, },
{ {
accessorKey: "type", accessorKey: "type",

View file

@ -32,6 +32,8 @@ import { createApiClient } from "@app/lib/api";
import { useEnvContext } from "@app/hooks/useEnvContext"; import { useEnvContext } from "@app/hooks/useEnvContext";
import { useState } from "react"; import { useState } from "react";
import { SwitchInput } from "@app/components/SwitchInput"; import { SwitchInput } from "@app/components/SwitchInput";
import Link from "next/link";
import { ArrowRight } from "lucide-react";
const GeneralFormSchema = z.object({ const GeneralFormSchema = z.object({
name: z.string().nonempty("Name is required"), name: z.string().nonempty("Name is required"),
@ -153,6 +155,20 @@ export default function GeneralPage() {
discovery for populating discovery for populating
container information, container information,
useful in resource targets. useful in resource targets.
<Link
href="https://docs.fossorial.io/Newt/overview#docker-socket-integration"
target="_blank"
rel="noopener noreferrer"
className="underline"
>
<span>
{" "}
Docker socket path
must be provided to
Newt in order to use
this feature.
</span>
</Link>
</FormDescription> </FormDescription>
</FormItem> </FormItem>
)} )}

View file

@ -82,7 +82,14 @@ export default function StepperForm() {
); );
const generateId = (name: string) => { const generateId = (name: string) => {
return name.toLowerCase().replace(/\s+/g, "-"); // Replace any character that is not a letter, number, space, or hyphen with a hyphen
// Also collapse multiple hyphens and trim
return name
.toLowerCase()
.replace(/[^a-z0-9\s-]/g, "-")
.replace(/\s+/g, "-")
.replace(/-+/g, "-")
.replace(/^-+|-+$/g, "");
}; };
async function orgSubmit(values: z.infer<typeof orgSchema>) { async function orgSubmit(values: z.infer<typeof orgSchema>) {
@ -207,23 +214,22 @@ export default function StepperForm() {
type="text" type="text"
{...field} {...field}
onChange={(e) => { onChange={(e) => {
const orgId = // Prevent "/" in orgName input
generateId( const sanitizedValue = e.target.value.replace(/\//g, "-");
e.target const orgId = generateId(sanitizedValue);
.value
);
orgForm.setValue( orgForm.setValue(
"orgId", "orgId",
orgId orgId
); );
orgForm.setValue( orgForm.setValue(
"orgName", "orgName",
e.target.value sanitizedValue
); );
debouncedCheckOrgIdAvailability( debouncedCheckOrgIdAvailability(
orgId orgId
); );
}} }}
value={field.value.replace(/\//g, "-")}
/> />
</FormControl> </FormControl>
<FormMessage /> <FormMessage />

View file

@ -95,7 +95,7 @@ export const ContainersSelector: FC<ContainerSelectorProps> = ({
<CredenzaTitle>Containers in {site.name}</CredenzaTitle> <CredenzaTitle>Containers in {site.name}</CredenzaTitle>
<CredenzaDescription> <CredenzaDescription>
Select any container to use as a hostname for this Select any container to use as a hostname for this
target. Click a port to use select a port. target. Click a port to use a port.
</CredenzaDescription> </CredenzaDescription>
</CredenzaHeader> </CredenzaHeader>
<CredenzaBody> <CredenzaBody>
@ -346,16 +346,19 @@ const DockerContainersTable: FC<{
{ {
id: "actions", id: "actions",
header: "Actions", header: "Actions",
cell: ({ row }) => ( cell: ({ row }) => {
<Button const ports = getExposedPorts(row.original);
variant="default" return (
size="sm" <Button
onClick={() => onContainerSelect(row.original)} variant="default"
disabled={row.original.state !== "running"} size="sm"
> onClick={() => onContainerSelect(row.original, ports[0])}
Select disabled={row.original.state !== "running"}
</Button> >
) Select
</Button>
);
}
} }
]; ];

View file

@ -21,7 +21,8 @@ export function useDockerSocket(site: Site) {
const api = createApiClient(useEnvContext()); const api = createApiClient(useEnvContext());
const { dockerSocketEnabled: isEnabled = true } = site || {}; const { dockerSocketEnabled: rawIsEnabled = true, type: siteType } = site || {};
const isEnabled = rawIsEnabled && siteType === "newt";
const { isAvailable = false, socketPath } = dockerSocket || {}; const { isAvailable = false, socketPath } = dockerSocket || {};
const checkDockerSocket = useCallback(async () => { const checkDockerSocket = useCallback(async () => {

21
src/lib/dataSize.ts Normal file
View file

@ -0,0 +1,21 @@
export function parseDataSize(sizeStr: string): number {
if (typeof sizeStr !== 'string') return 0;
const match = /^\s*([\d.]+)\s*([KMGT]?B)\s*$/i.exec(sizeStr);
if (!match) return 0;
const [ , numStr, unitRaw ] = match;
const num = parseFloat(numStr);
if (isNaN(num)) return 0;
const unit = unitRaw.toUpperCase();
const multipliers = {
B: 1,
KB: 1024,
MB: 1024 ** 2,
GB: 1024 ** 3,
TB: 1024 ** 4,
} as const;
return num * (multipliers[unit as keyof typeof multipliers] ?? 1);
}