chore: improve Team typing (#1669)

Some changes to improve the Team typing specifically at the `app<->api` boundary to support work for HDX-3156.
This commit is contained in:
Karl Power 2026-01-29 16:39:49 +01:00 committed by GitHub
parent 3aa8be0ae7
commit b8ab312a4c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 42 additions and 44 deletions

View file

@ -0,0 +1,7 @@
---
"@hyperdx/common-utils": patch
"@hyperdx/api": patch
"@hyperdx/app": patch
---
chore: improve Team typing

View file

@ -1,18 +1,13 @@
import { TeamClickHouseSettings } from '@hyperdx/common-utils/dist/types';
import { type Team } from '@hyperdx/common-utils/dist/types';
import mongoose, { Schema } from 'mongoose';
import { v4 as uuidv4 } from 'uuid';
type ObjectId = mongoose.Types.ObjectId;
export type ITeam = {
export interface ITeam extends Team {
_id: ObjectId;
id: string;
name: string;
allowedAuthMethods?: 'password'[];
apiKey: string;
hookId: string;
collectorAuthenticationEnforced: boolean;
} & TeamClickHouseSettings;
}
export type TeamDocument = mongoose.HydratedDocument<ITeam>;
export default mongoose.model<ITeam>(

View file

@ -3,7 +3,7 @@ import crypto from 'crypto';
import express from 'express';
import pick from 'lodash/pick';
import { z } from 'zod';
import { validateRequest } from 'zod-express-middleware';
import { processRequest, validateRequest } from 'zod-express-middleware';
import * as config from '@/config';
import {
@ -39,9 +39,7 @@ router.get('/', async (req, res, next) => {
'_id',
'allowedAuthMethods',
'apiKey',
'archive',
'name',
'slackAlert',
'createdAt',
]);
if (team == null) {
@ -91,7 +89,7 @@ router.patch(
router.patch(
'/clickhouse-settings',
validateRequest({
processRequest({
body: TeamClickHouseSettingsSchema,
}),
async (req, res, next) => {

View file

@ -29,7 +29,7 @@ export default function AuthPage({ action }: { action: 'register' | 'login' }) {
const { data: team, isLoading: teamIsLoading } = api.useTeam();
const router = useRouter();
const isLoggedIn = Boolean(!teamIsLoading && team && !team.isDemo);
const isLoggedIn = Boolean(!teamIsLoading && team);
useEffect(() => {
if (isLoggedIn) {

View file

@ -167,13 +167,13 @@ function IntegrationsSection() {
}
function TeamNameSection() {
const { data: team, isLoading, refetch: refetchTeam } = api.useTeam();
const { data: team, refetch: refetchTeam } = api.useTeam();
const setTeamName = api.useSetTeamName();
const hasAdminAccess = true;
const [isEditingTeamName, setIsEditingTeamName] = useState(false);
const form = useForm<{ name: string }>({
defaultValues: {
name: team.name,
name: team?.name,
},
});
@ -246,7 +246,7 @@ function TeamNameSection() {
</form>
) : (
<Group gap="lg">
<div className="fs-7">{team.name}</div>
<div className="fs-7">{team?.name}</div>
{hasAdminAccess && (
<Button
size="xs"

View file

@ -5,9 +5,10 @@ import type {
Alert,
PresetDashboard,
PresetDashboardFilter,
Team,
} from '@hyperdx/common-utils/dist/types';
import type { UseQueryOptions } from '@tanstack/react-query';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { useMutation, useQuery } from '@tanstack/react-query';
import { IS_LOCAL_MODE } from './config';
import { Dashboard } from './dashboard';
@ -304,13 +305,21 @@ const api = {
});
},
useTeam() {
return useQuery<any, Error>({
return useQuery({
queryKey: [`team`],
queryFn: () => {
if (IS_LOCAL_MODE) {
return null;
}
return hdxServer(`team`).json();
type TeamResponse = Pick<
Team,
'allowedAuthMethods' | 'apiKey' | 'name'
> & {
createdAt: string;
};
return hdxServer(`team`).json<TeamResponse>();
},
retry: 1,
});

View file

@ -251,16 +251,6 @@ export default function TeamMembersSection() {
</Group>
</Table.Td>
<Table.Td>
{team.shouldEnforceRBAC && !member.groupName && (
<Badge
variant="light"
color="red"
fw="normal"
tt="none"
>
Not Assigned to Group
</Badge>
)}
{member.groupName && (
<Badge
variant="light"

View file

@ -7,24 +7,10 @@ import {
Filter,
NumberFormat as _NumberFormat,
SavedSearchSchema,
WebhookService,
} from '@hyperdx/common-utils/dist/types';
export type NumberFormat = _NumberFormat;
export type Team = {
allowedAuthMethods: any[];
apiKey?: string;
name: string;
users: {
email: string;
hasPasswordAuth: boolean;
isCurrentUser: boolean;
name: string;
}[];
_id: string;
};
export type KeyValuePairs = {
'bool.names': string[];
'bool.values': number[];

View file

@ -594,6 +594,19 @@ export type TeamClickHouseSettings = z.infer<
typeof TeamClickHouseSettingsSchema
>;
export const TeamSchema = z
.object({
id: z.string(),
name: z.string(),
allowedAuthMethods: z.array(z.literal('password')).optional(),
apiKey: z.string(),
hookId: z.string(),
collectorAuthenticationEnforced: z.boolean(),
})
.merge(TeamClickHouseSettingsSchema);
export type Team = z.infer<typeof TeamSchema>;
// --------------------------
// TABLE SOURCES
// --------------------------