refactor: introduce dedicated identifier types for improved clarity and type safety
This commit is contained in:
@@ -7,9 +7,7 @@ import {
|
||||
} from 'react';
|
||||
import type { JSX } from 'react';
|
||||
import { CheckIcon, ChevronDownIcon } from '../../ui/icons';
|
||||
|
||||
|
||||
type CapabilityValue = string | number;
|
||||
import type { CapabilityValue } from '../../types/identifiers';
|
||||
|
||||
export interface CapabilityDropdownOption {
|
||||
value?: CapabilityValue | null;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
import type { ChangeEvent, FormEvent } from 'react';
|
||||
|
||||
type Identifier = string | number;
|
||||
import type { Identifier } from '../../types/identifiers';
|
||||
|
||||
interface ApiTokenEntry {
|
||||
id?: Identifier;
|
||||
@@ -125,21 +124,21 @@ const ApiTokensSection = ({
|
||||
const capabilitySelectionOptions = useMemo<CapabilitySelectionOption[]>(() => (
|
||||
Array.isArray(capabilities)
|
||||
? capabilities.map((capability) => {
|
||||
const capabilityText = `${capability ?? ''}`;
|
||||
if (!capabilityText.includes(':')) {
|
||||
return { value: capability, label: capabilityText };
|
||||
}
|
||||
const [namespace, action] = capabilityText.split(':');
|
||||
if (!namespace || !action) {
|
||||
return { value: capability, label: capabilityText };
|
||||
}
|
||||
const formattedNamespace = `${namespace.charAt(0).toUpperCase()}${namespace.slice(1)}`;
|
||||
const formattedAction = action.replace(/_/g, ' ');
|
||||
return {
|
||||
value: capability,
|
||||
label: `${formattedNamespace}: ${formattedAction}`,
|
||||
};
|
||||
})
|
||||
const capabilityText = `${capability ?? ''}`;
|
||||
if (!capabilityText.includes(':')) {
|
||||
return { value: capability, label: capabilityText };
|
||||
}
|
||||
const [namespace, action] = capabilityText.split(':');
|
||||
if (!namespace || !action) {
|
||||
return { value: capability, label: capabilityText };
|
||||
}
|
||||
const formattedNamespace = `${namespace.charAt(0).toUpperCase()}${namespace.slice(1)}`;
|
||||
const formattedAction = action.replace(/_/g, ' ');
|
||||
return {
|
||||
value: capability,
|
||||
label: `${formattedNamespace}: ${formattedAction}`,
|
||||
};
|
||||
})
|
||||
: []
|
||||
), [capabilities]);
|
||||
|
||||
|
||||
@@ -8,10 +8,7 @@ import React, {
|
||||
import type { SettingsSectionConfig } from '../SettingsModal';
|
||||
import { IconX } from '../../ui/icons';
|
||||
import CapabilityDropdown, { CapabilityDropdownOption } from '../components/CapabilityDropdown';
|
||||
|
||||
|
||||
type CapabilityValue = string | number;
|
||||
type CapabilitySetId = string | number;
|
||||
import type { CapabilitySetId, CapabilityValue } from '../../types/identifiers';
|
||||
|
||||
interface CapabilitySet {
|
||||
id: CapabilitySetId;
|
||||
|
||||
@@ -18,10 +18,10 @@ interface PasskeysSectionProps {
|
||||
passkeysSupported?: boolean | null;
|
||||
passkeysLoading?: boolean;
|
||||
registeringPasskey?: boolean;
|
||||
revokingPasskeyId?: string | number | null;
|
||||
revokingPasskeyId?: string | null;
|
||||
onRefreshPasskeys?: () => void | Promise<void>;
|
||||
onRegisterPasskey?: (args: { nickname?: string }) => Promise<RegisterPasskeyResult | undefined>;
|
||||
onRevokePasskey?: (id: string | number, reason?: string) => Promise<void>;
|
||||
onRevokePasskey?: (id: string, reason?: string) => Promise<void>;
|
||||
}
|
||||
|
||||
const PasskeysSection = ({
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
regenerateApiToken,
|
||||
type ApiTokenRecord,
|
||||
} from '../lib/apiClient';
|
||||
import type { ApiTokenId, CapabilitySetId } from '../types/identifiers';
|
||||
|
||||
interface ApiTokensResponse {
|
||||
token_info?: ApiTokenRecord;
|
||||
@@ -15,7 +16,7 @@ interface ApiTokensResponse {
|
||||
interface CreateTokenArgs {
|
||||
label?: string;
|
||||
expires_at?: string;
|
||||
capability_set_id?: string | number;
|
||||
capability_set_id?: CapabilitySetId;
|
||||
}
|
||||
|
||||
interface UseApiTokensArgs {
|
||||
@@ -28,13 +29,13 @@ interface UseApiTokensResult {
|
||||
tokens: ApiTokenRecord[];
|
||||
loading: boolean;
|
||||
creating: boolean;
|
||||
deletingId: string | number | null;
|
||||
regeneratingId: string | number | null;
|
||||
deletingId: ApiTokenId | null;
|
||||
regeneratingId: ApiTokenId | null;
|
||||
createdSecret: string | null;
|
||||
refresh: () => Promise<void>;
|
||||
create: (args?: CreateTokenArgs) => Promise<ApiTokensResponse | false>;
|
||||
revoke: (tokenId?: string | number | null) => Promise<boolean>;
|
||||
regenerate: (tokenId?: string | number | null) => Promise<boolean>;
|
||||
revoke: (tokenId?: ApiTokenId | null) => Promise<boolean>;
|
||||
regenerate: (tokenId?: ApiTokenId | null) => Promise<boolean>;
|
||||
dismissSecret: () => void;
|
||||
}
|
||||
|
||||
@@ -42,8 +43,8 @@ const useApiTokens = ({ notifyApiError, setStatusMessage, token }: UseApiTokensA
|
||||
const [tokens, setTokens] = useState<ApiTokenRecord[]>([]);
|
||||
const [loading] = useState(false);
|
||||
const [creating, setCreating] = useState(false);
|
||||
const [deletingId, setDeletingId] = useState<string | number | null>(null);
|
||||
const [regeneratingId, setRegeneratingId] = useState<string | number | null>(null);
|
||||
const [deletingId, setDeletingId] = useState<ApiTokenId | null>(null);
|
||||
const [regeneratingId, setRegeneratingId] = useState<ApiTokenId | null>(null);
|
||||
const [createdSecret, setCreatedSecret] = useState<string | null>(null);
|
||||
|
||||
const refresh = useCallback(async () => {
|
||||
@@ -65,7 +66,7 @@ const useApiTokens = ({ notifyApiError, setStatusMessage, token }: UseApiTokensA
|
||||
}
|
||||
setCreating(true);
|
||||
try {
|
||||
const payload: { capability_set_id: string | number; label?: string; expires_at?: string } = { capability_set_id };
|
||||
const payload: { capability_set_id: CapabilitySetId; label?: string; expires_at?: string } = { capability_set_id };
|
||||
if (label) {
|
||||
payload.label = label;
|
||||
}
|
||||
@@ -100,7 +101,7 @@ const useApiTokens = ({ notifyApiError, setStatusMessage, token }: UseApiTokensA
|
||||
);
|
||||
|
||||
const revoke = useCallback(
|
||||
async (tokenId?: string | number | null) => {
|
||||
async (tokenId?: string | null) => {
|
||||
if (!tokenId) {
|
||||
return false;
|
||||
}
|
||||
@@ -121,7 +122,7 @@ const useApiTokens = ({ notifyApiError, setStatusMessage, token }: UseApiTokensA
|
||||
);
|
||||
|
||||
const regenerate = useCallback(
|
||||
async (tokenId?: string | number | null) => {
|
||||
async (tokenId?: string | null) => {
|
||||
if (!tokenId) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -5,8 +5,7 @@ import {
|
||||
listCapabilitySets,
|
||||
updateCapabilitySet as updateCapabilitySetRequest,
|
||||
} from '../lib/apiClient';
|
||||
|
||||
type Identifier = string | number;
|
||||
import type { Identifier } from '../types/identifiers';
|
||||
|
||||
interface CapabilitySet {
|
||||
id?: Identifier;
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
listPasskeys,
|
||||
startPasskeyRegistration,
|
||||
} from '../lib/apiClient';
|
||||
import type { PasskeyId } from '../types/identifiers';
|
||||
|
||||
type StatusMessageFn = (message: string, variant?: string) => void;
|
||||
type NotifyApiErrorFn = (error: unknown, message: string) => void;
|
||||
@@ -27,7 +28,7 @@ type ApiError = {
|
||||
};
|
||||
|
||||
export interface PasskeyRecord {
|
||||
id?: string | number;
|
||||
id?: PasskeyId;
|
||||
nickname?: string;
|
||||
created_at?: string;
|
||||
createdAt?: string;
|
||||
@@ -79,11 +80,11 @@ interface UsePasskeysResult {
|
||||
passkeysSupported: boolean | null;
|
||||
passkeysLoading: boolean;
|
||||
registeringPasskey: boolean;
|
||||
revokingPasskeyId: string | number | null;
|
||||
revokingPasskeyId: PasskeyId | null;
|
||||
refreshPasskeys: () => Promise<void>;
|
||||
registerPasskey: (options?: { nickname?: string }) => Promise<RegisterPasskeyResult>;
|
||||
revokePasskey: (
|
||||
passkeyId: string | number,
|
||||
passkeyId: PasskeyId,
|
||||
reason?: string,
|
||||
) => Promise<RevokePasskeyResult>;
|
||||
}
|
||||
@@ -93,7 +94,7 @@ const usePasskeys = ({ notifyApiError, setStatusMessage, token }: UsePasskeysArg
|
||||
const [passkeysSupported, setPasskeysSupported] = useState<boolean | null>(null);
|
||||
const [passkeysLoading, setPasskeysLoading] = useState(false);
|
||||
const [registeringPasskey, setRegisteringPasskey] = useState(false);
|
||||
const [revokingPasskeyId, setRevokingPasskeyId] = useState<string | number | null>(null);
|
||||
const [revokingPasskeyId, setRevokingPasskeyId] = useState<PasskeyId | null>(null);
|
||||
|
||||
const refreshPasskeys = useCallback(async (): Promise<void> => {
|
||||
if (!token) {
|
||||
@@ -191,7 +192,7 @@ const usePasskeys = ({ notifyApiError, setStatusMessage, token }: UsePasskeysArg
|
||||
|
||||
const revokePasskey = useCallback(
|
||||
async (
|
||||
passkeyId: string | number,
|
||||
passkeyId: PasskeyId,
|
||||
reason?: string,
|
||||
): Promise<RevokePasskeyResult> => {
|
||||
if (passkeyId == null) {
|
||||
|
||||
Reference in New Issue
Block a user