diff --git a/.babelrc b/.babelrc index a6d99009a6..834b3316a9 100644 --- a/.babelrc +++ b/.babelrc @@ -10,8 +10,5 @@ "@babel/preset-react", "@babel/preset-typescript" ], - "plugins": [ - "@babel/plugin-transform-runtime", - "@babel/plugin-proposal-class-properties" - ] + "plugins": ["@babel/plugin-transform-runtime", "@babel/plugin-proposal-class-properties"] } diff --git a/.eslintrc.json b/.eslintrc.json index a3e135cfd9..ee57b0834c 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -18,19 +18,13 @@ "node": true }, "rules": { - "@typescript-eslint/consistent-type-imports": [ - "error", - { "prefer": "type-imports" } - ], + "@typescript-eslint/consistent-type-imports": ["error", { "prefer": "type-imports" }], "@typescript-eslint/explicit-module-boundary-types": "off", "@typescript-eslint/no-empty-function": "off", "@typescript-eslint/no-empty-interface": "off", "@typescript-eslint/ban-ts-comment": "off", "@typescript-eslint/no-non-null-assertion": "off", - "@typescript-eslint/no-unused-vars": [ - "error", - { "argsIgnorePattern": "^_" } - ], + "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], "@typescript-eslint/no-unnecessary-type-constraint": "off", "arrow-body-style": "off", "eqeqeq": "error", diff --git a/.prettierrc b/.prettierrc index fd496a820e..ec0ad27a3f 100644 --- a/.prettierrc +++ b/.prettierrc @@ -1,4 +1,5 @@ { + "printWidth": 92, "singleQuote": true, "semi": false } diff --git a/app/components/ErrorBoundary.tsx b/app/components/ErrorBoundary.tsx index 8b95141a1b..93ff0f92ef 100644 --- a/app/components/ErrorBoundary.tsx +++ b/app/components/ErrorBoundary.tsx @@ -21,7 +21,5 @@ function ErrorFallback({ error }: Props) { } export const ErrorBoundary = (props: { children: React.ReactNode }) => ( - - {props.children} - + {props.children} ) diff --git a/app/components/FormPage.tsx b/app/components/FormPage.tsx index 9ee1a77fc5..965d3be2ce 100644 --- a/app/components/FormPage.tsx +++ b/app/components/FormPage.tsx @@ -11,10 +11,7 @@ type FormPageProps = { * Dynamically load a form from the `forms` directory where id is the name of the form. * This is generally used to render form pages from the routes file. */ -export function FormPage({ - type, - ...props -}: FormPageProps) { +export function FormPage({ type, ...props }: FormPageProps) { const DynForm = useMemo( () => React.lazy(() => import(`../forms/${type}.tsx`)), [type] diff --git a/app/components/PageHeader.tsx b/app/components/PageHeader.tsx index 9077a21bf3..c891b62228 100644 --- a/app/components/PageHeader.tsx +++ b/app/components/PageHeader.tsx @@ -15,10 +15,7 @@ export function PageHeader() { typeof iconMatch?.route.icon === 'function' ? iconMatch.route.icon(iconMatch) : iconMatch?.route.icon - invariant( - title, - 'Page missing title, check routes config to ensure one is provided' - ) + invariant(title, 'Page missing title, check routes config to ensure one is provided') return ( (title && (
diff --git a/app/components/ProjectSelector.tsx b/app/components/ProjectSelector.tsx index efc71e2c20..417482753a 100644 --- a/app/components/ProjectSelector.tsx +++ b/app/components/ProjectSelector.tsx @@ -8,12 +8,7 @@ import cn from 'classnames' */ const BrandIcon = () => ( - + {
{orgName}
-
- {projectName || 'select a project'} -
+
{projectName || 'select a project'}
diff --git a/app/components/Sidebar.tsx b/app/components/Sidebar.tsx index 970fd905a7..864dfd5e85 100644 --- a/app/components/Sidebar.tsx +++ b/app/components/Sidebar.tsx @@ -34,9 +34,7 @@ interface SidebarNav { Sidebar.Nav = ({ children, heading }: SidebarNav) => { return (
- {heading ? ( - {heading} - ) : null} + {heading ? {heading} : null} @@ -50,9 +48,7 @@ interface SidebarFooter { Sidebar.Footer = ({ children }: SidebarFooter) => { return ( // TODO: The `w-[12.5rem] is hand calculated and very likely isn't what we want. Do something better here -
    - {children} -
+
    {children}
) } @@ -74,9 +70,7 @@ export const NavLinkItem = (props: { className={({ isActive }) => cn( 'flex h-7 items-center rounded p-1.5 text-sans-md hover:bg-raise svg:mr-2 svg:text-tertiary', - isActive - ? 'text-accent !bg-accent-secondary svg:!text-accent' - : 'text-default' + isActive ? 'text-accent !bg-accent-secondary svg:!text-accent' : 'text-default' ) } end={props.end} diff --git a/app/components/StatusBadge.tsx b/app/components/StatusBadge.tsx index 28dc1bbf98..c4e4d9079c 100644 --- a/app/components/StatusBadge.tsx +++ b/app/components/StatusBadge.tsx @@ -4,10 +4,7 @@ import type { BadgeColor, BadgeProps } from '@oxide/ui' import { Badge } from '@oxide/ui' import type { DiskState, InstanceState } from '@oxide/api' -const INSTANCE_COLORS: Record< - InstanceState, - Pick -> = { +const INSTANCE_COLORS: Record> = { creating: { color: 'notice' }, starting: { color: 'notice' }, running: { color: 'default' }, @@ -24,11 +21,7 @@ export const InstanceStatusBadge = (props: { status: InstanceState className?: string }) => ( - + {props.status} ) @@ -45,15 +38,8 @@ const DISK_COLORS: Record = { faulted: 'destructive', } -export const DiskStatusBadge = (props: { - status: DiskStateStr - className?: string -}) => ( - +export const DiskStatusBadge = (props: { status: DiskStateStr; className?: string }) => ( + {props.status} ) diff --git a/app/components/Tabs.tsx b/app/components/Tabs.tsx index 106e5a1507..d85d530ea6 100644 --- a/app/components/Tabs.tsx +++ b/app/components/Tabs.tsx @@ -27,9 +27,7 @@ export function Tabs(props: TabsProps) { }) const index = - searchTabId && tabIds.includes(searchTabId) - ? tabIds.indexOf(searchTabId) - : 0 + searchTabId && tabIds.includes(searchTabId) ? tabIds.indexOf(searchTabId) : 0 function onChange(newIdx: number) { // no arg is the canonical representation of first tab diff --git a/app/components/fields/DisksTableField.tsx b/app/components/fields/DisksTableField.tsx index 59033f0f26..9a8e13b7c4 100644 --- a/app/components/fields/DisksTableField.tsx +++ b/app/components/fields/DisksTableField.tsx @@ -2,13 +2,7 @@ import React, { useState } from 'react' import { useField } from 'formik' import { CreateDiskForm } from 'app/forms/disk-create' import { AttachDiskForm } from 'app/forms/disk-attach' -import { - Button, - Error16Icon, - FieldLabel, - MiniTable, - SideModal, -} from '@oxide/ui' +import { Button, Error16Icon, FieldLabel, MiniTable, SideModal } from '@oxide/ui' import type { FormValues } from '../../forms' type DiskTableItem = @@ -19,9 +13,9 @@ export function DisksTableField() { const [showDiskCreate, setShowDiskCreate] = useState(false) const [showDiskAttach, setShowDiskAttach] = useState(false) - const [, { value: items = [] }, { setValue: setItems }] = useField< - DiskTableItem[] - >({ name: 'disks' }) + const [, { value: items = [] }, { setValue: setItems }] = useField({ + name: 'disks', + }) return ( <> @@ -48,9 +42,7 @@ export function DisksTableField() { @@ -62,18 +54,10 @@ export function DisksTableField() { )}
- -
diff --git a/app/components/fields/NetworkInterfaceField.tsx b/app/components/fields/NetworkInterfaceField.tsx index 406e545bd1..8de63ffca7 100644 --- a/app/components/fields/NetworkInterfaceField.tsx +++ b/app/components/fields/NetworkInterfaceField.tsx @@ -1,10 +1,7 @@ import React, { useState } from 'react' import { useField } from 'formik' import { Button, Error16Icon, MiniTable, Radio, SideModal } from '@oxide/ui' -import type { - InstanceNetworkInterfaceAttachment, - NetworkInterfaceCreate, -} from '@oxide/api' +import type { InstanceNetworkInterfaceAttachment, NetworkInterfaceCreate } from '@oxide/api' import { RadioField } from '@oxide/form' import CreateNetworkInterfaceForm from 'app/forms/network-interface-create' @@ -17,8 +14,9 @@ export function NetworkInterfaceField() { */ const [oldParams, setOldParams] = useState([]) - const [, { value }, { setValue }] = - useField({ name: 'networkInterfaces' }) + const [, { value }, { setValue }] = useField({ + name: 'networkInterfaces', + }) return (
@@ -29,8 +27,7 @@ export function NetworkInterfaceField() { label="Network interface" className="pt-1" onChange={(event) => { - const newType = event.target - .value as InstanceNetworkInterfaceAttachment['type'] + const newType = event.target.value as InstanceNetworkInterfaceAttachment['type'] if (value.type === 'Create') { setOldParams(value.params) @@ -75,9 +72,7 @@ export function NetworkInterfaceField() { onClick={() => setValue({ type: 'Create', - params: value.params.filter( - (i) => i.name !== item.name - ), + params: value.params.filter((i) => i.name !== item.name), }) } > @@ -106,11 +101,7 @@ export function NetworkInterfaceField() { />
-
diff --git a/app/forms/__tests__/instance-create.e2e.ts b/app/forms/__tests__/instance-create.e2e.ts index 0425e3d20a..7b612b07ee 100644 --- a/app/forms/__tests__/instance-create.e2e.ts +++ b/app/forms/__tests__/instance-create.e2e.ts @@ -1,9 +1,7 @@ import { test, expect } from '@playwright/test' test.describe('Instance Create Form', () => { - test('can invoke instance create form from instances page', async ({ - page, - }) => { + test('can invoke instance create form from instances page', async ({ page }) => { await page.goto('/orgs/maze-war/projects/mock-project/instances') await page.locator('text="New Instance"').click() await expect(page.locator('h1:has-text("Create instance")')).toBeVisible() diff --git a/app/forms/index.spec.ts b/app/forms/index.spec.ts index c6dc616226..7607b6642a 100644 --- a/app/forms/index.spec.ts +++ b/app/forms/index.spec.ts @@ -12,9 +12,7 @@ test('FormTypes must contain references to all forms', async () => { .map((f) => f.slice(0, -4)) .sort() - const AST = await parse( - await fs.readFile(path.join(__dirname, './index.ts'), 'utf8') - ) + const AST = await parse(await fs.readFile(path.join(__dirname, './index.ts'), 'utf8')) traverse(AST, { TSInterfaceDeclaration(path) { const name = path.node.id.name diff --git a/app/forms/index.ts b/app/forms/index.ts index d108b81355..fcf7778fee 100644 --- a/app/forms/index.ts +++ b/app/forms/index.ts @@ -31,19 +31,14 @@ export interface FormTypes { 'vpc-create': typeof CreateVpcForm } -export type FormValues = ExtractFormValues< - FormTypes[K] -> +export type FormValues = ExtractFormValues /** * A form that's built out ahead of time and intended to be re-used dynamically. Fields * that are expected to be provided by default are set to optional. */ export type PrebuiltFormProps = Omit< - Optional< - FormProps, - 'id' | 'title' | 'initialValues' | 'onSubmit' | 'mutation' - >, + Optional, 'id' | 'title' | 'initialValues' | 'onSubmit' | 'mutation'>, 'children' > & { children?: never @@ -54,9 +49,7 @@ export type PrebuiltFormProps = Omit< /** * A utility type for a prebuilt form that extends another form */ -export type ExtendedPrebuiltFormProps = C extends ComponentType< - infer B -> +export type ExtendedPrebuiltFormProps = C extends ComponentType ? // eslint-disable-next-line @typescript-eslint/no-explicit-any B extends PrebuiltFormProps ? PrebuiltFormProps diff --git a/app/forms/instance-create.tsx b/app/forms/instance-create.tsx index b859b8b0b0..ae14022de1 100644 --- a/app/forms/instance-create.tsx +++ b/app/forms/instance-create.tsx @@ -89,15 +89,17 @@ export default function CreateInstanceForm({ ((values) => { const instance = INSTANCE_SIZES.find( (option) => option.id === values['type'] - ) || { memory: 0, ncpus: 0 } + ) || { + memory: 0, + ncpus: 0, + } createInstance.mutate({ ...pageParams, body: { name: values['name'], hostname: values.hostname, description: `An instance in project: ${pageParams.projectName}`, - memory: filesize(instance.memory, { output: 'object', base: 2 }) - .value, + memory: filesize(instance.memory, { output: 'object', base: 2 }).value, ncpus: instance.ncpus, disks: values.disks, }, @@ -118,8 +120,8 @@ export default function CreateInstanceForm({ General Purpose - General purpose instances provide a good balance of CPU, memory, and - high performance storage; well suited for a wide range of use cases. + General purpose instances provide a good balance of CPU, memory, and high + performance storage; well suited for a wide range of use cases. {renderLargeRadioCards('general')} @@ -219,10 +221,7 @@ export default function CreateInstanceForm({ - + {title} @@ -237,11 +236,7 @@ interface DistroRadioCardProps { value: string Icon: React.ComponentType<{ className: string }> } -const renderDistroRadioCard = ({ - label, - value, - Icon, -}: DistroRadioCardProps) => { +const renderDistroRadioCard = ({ label, value, Icon }: DistroRadioCardProps) => { return (
@@ -253,22 +248,19 @@ const renderDistroRadioCard = ({ } const renderLargeRadioCards = (category: string) => { - return INSTANCE_SIZES.filter((option) => option.category === category).map( - (option) => ( - -
- {option.ncpus}{' '} - - CPU{option.ncpus === 1 ? '' : 's'} - -
-
- {option.memory}{' '} - GB RAM -
-
- ) - ) + return INSTANCE_SIZES.filter((option) => option.category === category).map((option) => ( + +
+ {option.ncpus}{' '} + + CPU{option.ncpus === 1 ? '' : 's'} + +
+
+ {option.memory} GB RAM +
+
+ )) } // This data structure is completely made up for the purposes of demonstration diff --git a/app/forms/network-interface-create.tsx b/app/forms/network-interface-create.tsx index 7968ea14f6..49b88f191d 100644 --- a/app/forms/network-interface-create.tsx +++ b/app/forms/network-interface-create.tsx @@ -28,24 +28,18 @@ export default function CreateNetworkInterfaceForm({ const queryClient = useApiQueryClient() const pathParams = useParams('orgName', 'projectName') - const createNetworkInterface = useApiMutation( - 'instanceNetworkInterfacesPost', - { - onSuccess(data) { - const { instanceName, ...others } = pathParams - invariant( - instanceName, - 'instanceName is required when posting a network interface' - ) - queryClient.invalidateQueries('instanceNetworkInterfacesGet', { - instanceName, - ...others, - }) - onSuccess?.(data) - }, - onError, - } - ) + const createNetworkInterface = useApiMutation('instanceNetworkInterfacesPost', { + onSuccess(data) { + const { instanceName, ...others } = pathParams + invariant(instanceName, 'instanceName is required when posting a network interface') + queryClient.invalidateQueries('instanceNetworkInterfacesGet', { + instanceName, + ...others, + }) + onSuccess?.(data) + }, + onError, + }) return (
, title: 'Success!', diff --git a/app/forms/vpc-create.tsx b/app/forms/vpc-create.tsx index f428cc530b..a190d8ac72 100644 --- a/app/forms/vpc-create.tsx +++ b/app/forms/vpc-create.tsx @@ -64,12 +64,7 @@ export function CreateVpcForm({ > - + {title} diff --git a/app/hooks/use-quick-actions.tsx b/app/hooks/use-quick-actions.tsx index 2309428556..07e7c5bbe5 100644 --- a/app/hooks/use-quick-actions.tsx +++ b/app/hooks/use-quick-actions.tsx @@ -23,8 +23,7 @@ const useStore = create((set) => ({ items: [], add: (toAdd) => set(({ items }) => ({ items: removeByValue(items, toAdd).concat(toAdd) })), - remove: (toRemove) => - set(({ items }) => ({ items: removeByValue(items, toRemove) })), + remove: (toRemove) => set(({ items }) => ({ items: removeByValue(items, toRemove) })), })) /** diff --git a/app/layouts/ProjectLayout.tsx b/app/layouts/ProjectLayout.tsx index 7f8f18ef7f..e52e2658d6 100644 --- a/app/layouts/ProjectLayout.tsx +++ b/app/layouts/ProjectLayout.tsx @@ -40,10 +40,7 @@ const ProjectLayout = () => { { value: 'Networking', path: 'vpcs' }, ] // filter out the entry for the path we're currently on - .filter( - (i) => - !matchPath(`/orgs/:org/projects/:project/${i.path}`, currentPath) - ) + .filter((i) => !matchPath(`/orgs/:org/projects/:project/${i.path}`, currentPath)) .map((i) => ({ navGroup: `Project '${projectName}'`, value: i.value, diff --git a/app/pages/OrgsPage.tsx b/app/pages/OrgsPage.tsx index 18b9f4032e..9f967dc141 100644 --- a/app/pages/OrgsPage.tsx +++ b/app/pages/OrgsPage.tsx @@ -30,10 +30,7 @@ const OrgsPage = () => { return ( <> - + New Organization diff --git a/app/pages/ProjectsPage.tsx b/app/pages/ProjectsPage.tsx index 7a86d4d234..0a30284b01 100644 --- a/app/pages/ProjectsPage.tsx +++ b/app/pages/ProjectsPage.tsx @@ -42,10 +42,7 @@ const ProjectsPage = () => { - `/orgs/${orgName}/projects/${name}`)} - /> + `/orgs/${orgName}/projects/${name}`)} />
diff --git a/app/pages/__tests__/ProjectCreatePage.spec.tsx b/app/pages/__tests__/ProjectCreatePage.spec.tsx index c5368351d3..f64782a929 100644 --- a/app/pages/__tests__/ProjectCreatePage.spec.tsx +++ b/app/pages/__tests__/ProjectCreatePage.spec.tsx @@ -18,21 +18,16 @@ async function enterName(value: string) { const formUrl = `/orgs/${org.name}/projects/new` describe('ProjectCreatePage', () => { - it.todo( - 'shows message for known error code in project create code map', - async () => { - renderAppAt(formUrl) - await enterName(project.name) // already exists - - clickByRole('button', 'Create project') - - await screen.findByText( - 'A project with that name already exists in this organization' - ) - // don't nav away - expect(window.location.pathname).toEqual(formUrl) - } - ) + it.todo('shows message for known error code in project create code map', async () => { + renderAppAt(formUrl) + await enterName(project.name) // already exists + + clickByRole('button', 'Create project') + + await screen.findByText('A project with that name already exists in this organization') + // don't nav away + expect(window.location.pathname).toEqual(formUrl) + }) it.todo('shows message for known error code in global code map', async () => { override('post', projectsUrl, 403, { error_code: 'Forbidden' }) diff --git a/app/pages/project/instances/InstancesPage.tsx b/app/pages/project/instances/InstancesPage.tsx index 308ac467bf..bd32883795 100644 --- a/app/pages/project/instances/InstancesPage.tsx +++ b/app/pages/project/instances/InstancesPage.tsx @@ -45,14 +45,10 @@ export const InstancesPage = () => { ) ) - const { Table, Column } = useQueryTable( - 'projectInstancesGet', - projectParams, - { - refetchInterval: 5000, - keepPreviousData: true, - } - ) + const { Table, Column } = useQueryTable('projectInstancesGet', projectParams, { + refetchInterval: 5000, + keepPreviousData: true, + }) if (!instances) return null @@ -70,8 +66,7 @@ export const InstancesPage = () => { - `/orgs/${orgName}/projects/${projectName}/instances/${name}` + (name) => `/orgs/${orgName}/projects/${projectName}/instances/${name}` )} /> - successToast(`Starting instance '${instanceName}'`), + onSuccess: () => successToast(`Starting instance '${instanceName}'`), } ) }, @@ -59,8 +58,7 @@ export const useMakeInstanceActions = ( stopInstance.mutate( { ...projectParams, instanceName }, { - onSuccess: () => - successToast(`Stopping instance '${instanceName}'`), + onSuccess: () => successToast(`Stopping instance '${instanceName}'`), } ) }, @@ -72,8 +70,7 @@ export const useMakeInstanceActions = ( rebootInstance.mutate( { ...projectParams, instanceName }, { - onSuccess: () => - successToast(`Rebooting instance '${instanceName}'`), + onSuccess: () => successToast(`Rebooting instance '${instanceName}'`), } ) }, diff --git a/app/pages/project/instances/instance/InstancePage.tsx b/app/pages/project/instances/instance/InstancePage.tsx index 4bb880625c..7282304c42 100644 --- a/app/pages/project/instances/instance/InstancePage.tsx +++ b/app/pages/project/instances/instance/InstancePage.tsx @@ -20,20 +20,15 @@ export const InstancePage = () => { const projectParams = pick(instanceParams, 'projectName', 'orgName') const makeActions = useMakeInstanceActions(projectParams, { onSuccess: () => { - queryClient.invalidateQueries( - 'projectInstancesGetInstance', - instanceParams - ) + queryClient.invalidateQueries('projectInstancesGetInstance', instanceParams) }, // go to project instances list since there's no more instance onDelete: () => navigate('..'), }) - const { data: instance } = useApiQuery( - 'projectInstancesGetInstance', - instanceParams, - { refetchInterval: 5000 } - ) + const { data: instance } = useApiQuery('projectInstancesGetInstance', instanceParams, { + refetchInterval: 5000, + }) const actions = useMemo( () => (instance ? makeActions(instance) : []), [instance, makeActions] diff --git a/app/pages/project/instances/instance/tabs/MetricsTab.tsx b/app/pages/project/instances/instance/tabs/MetricsTab.tsx index 6f37d654db..f9582644df 100644 --- a/app/pages/project/instances/instance/tabs/MetricsTab.tsx +++ b/app/pages/project/instances/instance/tabs/MetricsTab.tsx @@ -1,12 +1,5 @@ import React from 'react' -import { - Area, - CartesianGrid, - ComposedChart, - Line, - XAxis, - YAxis, -} from 'recharts' +import { Area, CartesianGrid, ComposedChart, Line, XAxis, YAxis } from 'recharts' const data = [ { name: '9:50', amt: 200, limit: 600 }, diff --git a/app/pages/project/networking/VpcPage/VpcPage.e2e.ts b/app/pages/project/networking/VpcPage/VpcPage.e2e.ts index bd3daccc6c..b032500229 100644 --- a/app/pages/project/networking/VpcPage/VpcPage.e2e.ts +++ b/app/pages/project/networking/VpcPage/VpcPage.e2e.ts @@ -32,12 +32,7 @@ test.describe('VpcPage', () => { await expect(rows.nth(1).locator('text="1.1.1.2/24"')).toBeVisible() }) - const defaultRules = [ - 'allow-internal-inbound', - 'allow-ssh', - 'allow-icmp', - 'allow-rdp', - ] + const defaultRules = ['allow-internal-inbound', 'allow-ssh', 'allow-icmp', 'allow-rdp'] test('can create firewall rule', async ({ page }) => { await page.goto('/orgs/maze-war/projects/mock-project/vpcs/mock-vpc') @@ -80,9 +75,7 @@ test.describe('VpcPage', () => { await page.locator('text="Add host filter"').click() // host is added to hosts table - await expect( - page.locator('td:has-text("host-filter-instance")') - ).toBeVisible() + await expect(page.locator('td:has-text("host-filter-instance")')).toBeVisible() // TODO: test invalid port range once I put an error message in there await page.fill('text="Port filter"', '123-456') @@ -105,9 +98,7 @@ test.describe('VpcPage', () => { // target shows up in target cell await expect(page.locator('text=vpcmy-target-vpc')).toBeVisible() // other stuff filled out shows up in the filters column - await expect( - page.locator('text=instancehost-filter-instanceUDP123-456') - ).toBeVisible() + await expect(page.locator('text=instancehost-filter-instanceUDP123-456')).toBeVisible() await expect(rows).toHaveCount(5) for (const name of defaultRules) { @@ -167,9 +158,7 @@ test.describe('VpcPage', () => { await page.locator('text="Add host filter"').click() // new host is added to hosts table - await expect( - page.locator('td:has-text("edit-filter-instance")') - ).toBeVisible() + await expect(page.locator('td:has-text("edit-filter-instance")')).toBeVisible() // submit the form await page.locator('text="Update rule"').click() @@ -184,9 +173,7 @@ test.describe('VpcPage', () => { await expect(rows).toHaveCount(4) // new target shows up in target cell - await expect( - page.locator('text=instanceedit-filter-instanceICMP') - ).toBeVisible() + await expect(page.locator('text=instanceedit-filter-instanceICMP')).toBeVisible() // other 3 rules are still there const rest = defaultRules.filter((r) => r !== 'allow-icmp') diff --git a/app/pages/project/networking/VpcPage/VpcPage.tsx b/app/pages/project/networking/VpcPage/VpcPage.tsx index 314c305343..d91a2a2fa5 100644 --- a/app/pages/project/networking/VpcPage/VpcPage.tsx +++ b/app/pages/project/networking/VpcPage/VpcPage.tsx @@ -19,12 +19,8 @@ export const VpcPage = () => { <> - - {vpc?.description} - - - {vpc?.dnsName} - + {vpc?.description} + {vpc?.dnsName} diff --git a/app/pages/project/networking/VpcPage/modals/firewall-rules.tsx b/app/pages/project/networking/VpcPage/modals/firewall-rules.tsx index 263c9d6ca1..0bc8abe4d3 100644 --- a/app/pages/project/networking/VpcPage/modals/firewall-rules.tsx +++ b/app/pages/project/networking/VpcPage/modals/firewall-rules.tsx @@ -17,11 +17,7 @@ import { TextFieldError, TextFieldHint, } from '@oxide/ui' -import type { - ErrorResponse, - VpcFirewallRule, - VpcFirewallRuleUpdate, -} from '@oxide/api' +import type { ErrorResponse, VpcFirewallRule, VpcFirewallRuleUpdate } from '@oxide/api' import { parsePortRange, useApiMutation, @@ -90,14 +86,8 @@ const CommonForm = ({ id, error }: FormProps) => { Priority - - Must be 0–65535 - - + Must be 0–65535 +
@@ -148,9 +138,7 @@ const CommonForm = ({ id, error }: FormProps) => { values.targetType && values.targetValue && // TODO: validate !values.targets.some( - (t) => - t.value === values.targetValue && - t.type === values.targetType + (t) => t.value === values.targetValue && t.type === values.targetType ) ) { setFieldValue('targets', [ @@ -224,11 +212,7 @@ const CommonForm = ({ id, error }: FormProps) => { For IP, an address. For the rest, a name. [TODO: copy] - +
@@ -243,8 +227,7 @@ const CommonForm = ({ id, error }: FormProps) => { values.hostType && values.hostValue && // TODO: validate !values.hosts.some( - (t) => - t.value === values.hostValue || t.type === values.hostType + (t) => t.value === values.hostValue || t.type === values.hostType ) ) { setFieldValue('hosts', [ @@ -300,11 +283,7 @@ const CommonForm = ({ id, error }: FormProps) => { A single port (1234) or a range (1234-2345) - +
{ return ( <>
- { - +
) diff --git a/app/pages/project/networking/VpcPage/tabs/VpcSubnetsTab.tsx b/app/pages/project/networking/VpcPage/tabs/VpcSubnetsTab.tsx index 1ac19bac1e..e0b0fb8c35 100644 --- a/app/pages/project/networking/VpcPage/tabs/VpcSubnetsTab.tsx +++ b/app/pages/project/networking/VpcPage/tabs/VpcSubnetsTab.tsx @@ -24,11 +24,7 @@ export const VpcSubnetsTab = () => { return ( <>
- { onDismiss={() => setEditing(null)} > {editing && ( - setEditing(null)} - /> + setEditing(null)} /> )}
diff --git a/app/pages/project/networking/VpcsPage.tsx b/app/pages/project/networking/VpcsPage.tsx index a966ed721b..056143ce11 100644 --- a/app/pages/project/networking/VpcsPage.tsx +++ b/app/pages/project/networking/VpcsPage.tsx @@ -29,19 +29,14 @@ export const VpcsPage = () => { return ( <> - + New VPC `/orgs/${orgName}/projects/${projectName}/vpcs/${name}` - )} + cell={linkCell((name) => `/orgs/${orgName}/projects/${projectName}/vpcs/${name}`)} /> diff --git a/app/routes.tsx b/app/routes.tsx index 655f4d3b84..a9297bfb32 100644 --- a/app/routes.tsx +++ b/app/routes.tsx @@ -68,11 +68,7 @@ export const routes = ( } /> - } - icon={} - title="Organizations" - > + } icon={} title="Organizations"> } /> {/* PROJECT */} - } - crumb={projectCrumb} - > + } crumb={projectCrumb}> } /> - } - > + }> } /> { }) it("addSuffix option adds 'ago'", () => { - expect(timeAgoAbbr(subDays(baseDate, 200), { addSuffix: true })).toEqual( - '7mo ago' - ) - expect(timeAgoAbbr(subDays(baseDate, 3), { addSuffix: true })).toEqual( - '3d ago' - ) + expect(timeAgoAbbr(subDays(baseDate, 200), { addSuffix: true })).toEqual('7mo ago') + expect(timeAgoAbbr(subDays(baseDate, 3), { addSuffix: true })).toEqual('3d ago') }) }) diff --git a/app/util/errors.spec.ts b/app/util/errors.spec.ts index 775ea2e050..ed65814375 100644 --- a/app/util/errors.spec.ts +++ b/app/util/errors.spec.ts @@ -5,8 +5,7 @@ const parseError = { error: { requestId: '1', errorCode: null, - message: - 'unable to parse body: hello there, you have an error at line 129 column 4', + message: 'unable to parse body: hello there, you have an error at line 129 column 4', }, } as ErrorResponse @@ -52,9 +51,7 @@ describe('getServerError', () => { }) it('falls back to server error message if code not found', () => { - expect(getServerError(alreadyExists, { NotACode: 'stop that' })).toEqual( - 'whatever' - ) + expect(getServerError(alreadyExists, { NotACode: 'stop that' })).toEqual('whatever') }) it('uses global map of generic codes for, e.g., 403s', () => { diff --git a/app/util/errors.ts b/app/util/errors.ts index 4ac686d206..603aa2596b 100644 --- a/app/util/errors.ts +++ b/app/util/errors.ts @@ -4,9 +4,7 @@ import { capitalize } from '@oxide/util' export function getParseError(message: string | undefined): string | undefined { if (!message) return undefined - const inner = /^unable to parse body: (.+) at line \d+ column \d+$/.exec( - message - )?.[1] + const inner = /^unable to parse body: (.+) at line \d+ column \d+$/.exec(message)?.[1] return inner && capitalize(inner) } diff --git a/codemods/add-responsive-viewbox.icons.js b/codemods/add-responsive-viewbox.icons.js index 1f46dd17c9..0c85ce1476 100644 --- a/codemods/add-responsive-viewbox.icons.js +++ b/codemods/add-responsive-viewbox.icons.js @@ -9,11 +9,7 @@ export default function transformer(file, api) { const j = api.jscodeshift const source = j(file.source) - if ( - !file.path.endsWith('.tsx') || - !file.path.toLowerCase().includes('responsive') - ) - return + if (!file.path.endsWith('.tsx') || !file.path.toLowerCase().includes('responsive')) return // Grab width value and remove width prop const widthProp = source.find(j.JSXAttribute, { name: { name: 'width' } }) @@ -30,10 +26,7 @@ export default function transformer(file, api) { .find(j.JSXOpeningElement, { name: { name: 'svg' } }) .map((s) => { s.node.attributes.unshift( - j.jsxAttribute( - j.jsxIdentifier('viewBox'), - j.literal(`0 0 ${width} ${height}`) - ) + j.jsxAttribute(j.jsxIdentifier('viewBox'), j.literal(`0 0 ${width} ${height}`)) ) }) .toSource() diff --git a/libs/api-mocks/msw/db.ts b/libs/api-mocks/msw/db.ts index 9a38ab02a4..f27b333437 100644 --- a/libs/api-mocks/msw/db.ts +++ b/libs/api-mocks/msw/db.ts @@ -53,9 +53,7 @@ export function lookupOrg(req: Req): Result> { return Ok(org) } -export function lookupProject( - req: Req -): Result> { +export function lookupProject(req: Req): Result> { const [org, err] = lookupOrg(req) if (err) return Err(err) @@ -80,9 +78,7 @@ export function lookupVpc(req: Req): Result> { return Ok(vpc) } -export function lookupInstance( - req: Req -): Result> { +export function lookupInstance(req: Req): Result> { const [project, err] = lookupProject(req) if (err) return Err(err) @@ -106,9 +102,7 @@ export function lookupDisk(req: Req): Result> { return Ok(disk) } -export function lookupVpcSubnet( - req: Req -): Result> { +export function lookupVpcSubnet(req: Req): Result> { const [vpc, err] = lookupVpc(req) if (err) return Err(err) diff --git a/libs/api-mocks/msw/handlers.ts b/libs/api-mocks/msw/handlers.ts index 3b0ba7d744..bc16dc86e9 100644 --- a/libs/api-mocks/msw/handlers.ts +++ b/libs/api-mocks/msw/handlers.ts @@ -68,26 +68,25 @@ export const handlers = [ (req, res) => res(json({ items: db.orgs })) ), - rest.post< - Json, - never, - Json | PostErr - >('/api/organizations', (req, res) => { - const alreadyExists = db.orgs.some((o) => o.name === req.body.name) - if (alreadyExists) return res(alreadyExistsErr) - - if (!req.body.name) { - return res(badRequest('name requires at least one character')) - } + rest.post, never, Json | PostErr>( + '/api/organizations', + (req, res) => { + const alreadyExists = db.orgs.some((o) => o.name === req.body.name) + if (alreadyExists) return res(alreadyExistsErr) - const newOrg: Json = { - id: genId('org'), - ...req.body, - ...getTimestamps(), + if (!req.body.name) { + return res(badRequest('name requires at least one character')) + } + + const newOrg: Json = { + id: genId('org'), + ...req.body, + ...getTimestamps(), + } + db.orgs.push(newOrg) + return res(json(newOrg, 201)) } - db.orgs.push(newOrg) - return res(json(newOrg, 201)) - }), + ), rest.get | GetErr>( '/api/organizations/:orgName', @@ -179,11 +178,7 @@ export const handlers = [ } ), - rest.post< - Json, - ProjectParams, - Json | PostErr - >( + rest.post, ProjectParams, Json | PostErr>( '/api/organizations/:orgName/projects/:projectName/instances', (req, res) => { const [project, err] = lookupProject(req) @@ -366,11 +361,7 @@ export const handlers = [ } ), - rest.post< - Json, - VpcParams, - Json | PostErr - >( + rest.post, VpcParams, Json | PostErr>( '/api/organizations/:orgName/projects/:projectName/vpcs/:vpcName/subnets', (req, res) => { const [vpc, err] = lookupVpc(req) @@ -400,11 +391,7 @@ export const handlers = [ } ), - rest.put< - Json, - VpcSubnetParams, - Json | PostErr - >( + rest.put, VpcSubnetParams, Json | PostErr>( '/api/organizations/:orgName/projects/:projectName/vpcs/:vpcName/subnets/:subnetName', (req, res, ctx) => { const [subnet, err] = lookupVpcSubnet(req) diff --git a/libs/api/__generated__/Api.ts b/libs/api/__generated__/Api.ts index 5b1a8820be..22f9c1d95c 100644 --- a/libs/api/__generated__/Api.ts +++ b/libs/api/__generated__/Api.ts @@ -714,11 +714,7 @@ export type RouterRouteCreateParams = { * * See [RFD-21](https://rfd.shared.oxide.computer/rfd/0021#concept-router) for more context */ -export type RouterRouteKind = - | 'default' - | 'vpc_subnet' - | 'vpc_peering' - | 'custom' +export type RouterRouteKind = 'default' | 'vpc_subnet' | 'vpc_peering' | 'custom' /** * A single page of results @@ -1403,10 +1399,7 @@ export type NameSortMode = 'name-ascending' /** * Supported set of sort modes for scanning by name or id */ -export type NameOrIdSortMode = - | 'name-ascending' - | 'name-descending' - | 'id-ascending' +export type NameOrIdSortMode = 'name-ascending' | 'name-descending' | 'id-ascending' export interface HardwareRacksGetParams { limit?: number | null @@ -2050,8 +2043,7 @@ export interface UsersGetUserParams { userName: Name } -const camelToSnake = (s: string) => - s.replace(/[A-Z]/g, (l) => '_' + l.toLowerCase()) +const camelToSnake = (s: string) => s.replace(/[A-Z]/g, (l) => '_' + l.toLowerCase()) const snakeToCamel = (s: string) => s.replace(/_./g, (l) => l[1].toUpperCase()) @@ -2116,10 +2108,7 @@ export interface FullRequestParams extends Omit { cancelToken?: CancelToken } -export type RequestParams = Omit< - FullRequestParams, - 'body' | 'method' | 'query' | 'path' -> +export type RequestParams = Omit export interface ApiConfig { baseUrl?: string @@ -2142,9 +2131,7 @@ export type SuccessResponse = Response & { error: null } -export type ApiResponse = - | SuccessResponse - | ErrorResponse +export type ApiResponse = SuccessResponse | ErrorResponse type CancelToken = Symbol | string | number @@ -2164,8 +2151,7 @@ const toQueryString = (rawQuery?: QueryParamsType): string => export class HttpClient { public baseUrl: string = '' private abortControllers = new Map() - private customFetch = (...fetchParams: Parameters) => - fetch(...fetchParams) + private customFetch = (...fetchParams: Parameters) => fetch(...fetchParams) private baseApiParams: RequestParams = { credentials: 'same-origin', @@ -2189,9 +2175,7 @@ export class HttpClient { } } - private createAbortSignal = ( - cancelToken: CancelToken - ): AbortSignal | undefined => { + private createAbortSignal = (cancelToken: CancelToken): AbortSignal | undefined => { if (this.abortControllers.has(cancelToken)) { const abortController = this.abortControllers.get(cancelToken) if (abortController) { @@ -2270,10 +2254,7 @@ export class Api extends HttpClient { /** * List racks in the system. */ - hardwareRacksGet: ( - query: HardwareRacksGetParams, - params: RequestParams = {} - ) => + hardwareRacksGet: (query: HardwareRacksGetParams, params: RequestParams = {}) => this.request({ path: `/hardware/racks`, method: 'GET', @@ -2297,10 +2278,7 @@ export class Api extends HttpClient { /** * List sleds in the system. */ - hardwareSledsGet: ( - query: HardwareSledsGetParams, - params: RequestParams = {} - ) => + hardwareSledsGet: (query: HardwareSledsGetParams, params: RequestParams = {}) => this.request({ path: `/hardware/sleds`, method: 'GET', @@ -2335,11 +2313,7 @@ export class Api extends HttpClient { /** * Create a global image. */ - imagesPost: ( - query: ImagesPostParams, - data: ImageCreate, - params: RequestParams = {} - ) => + imagesPost: (query: ImagesPostParams, data: ImageCreate, params: RequestParams = {}) => this.request({ path: `/images`, method: 'POST', @@ -2350,10 +2324,7 @@ export class Api extends HttpClient { /** * Get a global image. */ - imagesGetImage: ( - { imageName }: ImagesGetImageParams, - params: RequestParams = {} - ) => + imagesGetImage: ({ imageName }: ImagesGetImageParams, params: RequestParams = {}) => this.request({ path: `/images/${imageName}`, method: 'GET', @@ -2373,11 +2344,7 @@ export class Api extends HttpClient { ...params, }), - spoofLogin: ( - query: SpoofLoginParams, - data: LoginParams, - params: RequestParams = {} - ) => + spoofLogin: (query: SpoofLoginParams, data: LoginParams, params: RequestParams = {}) => this.request({ path: `/login`, method: 'POST', @@ -2395,10 +2362,7 @@ export class Api extends HttpClient { /** * List all organizations. */ - organizationsGet: ( - query: OrganizationsGetParams, - params: RequestParams = {} - ) => + organizationsGet: (query: OrganizationsGetParams, params: RequestParams = {}) => this.request({ path: `/organizations`, method: 'GET', @@ -2688,11 +2652,7 @@ export class Api extends HttpClient { * Delete an instance from a project. */ projectInstancesDeleteInstance: ( - { - instanceName, - orgName, - projectName, - }: ProjectInstancesDeleteInstanceParams, + { instanceName, orgName, projectName }: ProjectInstancesDeleteInstanceParams, params: RequestParams = {} ) => this.request({ @@ -2743,11 +2703,7 @@ export class Api extends HttpClient { * Migrate an instance to a different propolis-server, possibly on a different sled. */ projectInstancesMigrateInstance: ( - { - instanceName, - orgName, - projectName, - }: ProjectInstancesMigrateInstanceParams, + { instanceName, orgName, projectName }: ProjectInstancesMigrateInstanceParams, data: InstanceMigrate, params: RequestParams = {} ) => @@ -2762,12 +2718,7 @@ export class Api extends HttpClient { * List network interfaces attached to this instance. */ instanceNetworkInterfacesGet: ( - { - instanceName, - orgName, - projectName, - ...query - }: InstanceNetworkInterfacesGetParams, + { instanceName, orgName, projectName, ...query }: InstanceNetworkInterfacesGetParams, params: RequestParams = {} ) => this.request({ @@ -2781,11 +2732,7 @@ export class Api extends HttpClient { * Create a network interface for an instance. */ instanceNetworkInterfacesPost: ( - { - instanceName, - orgName, - projectName, - }: InstanceNetworkInterfacesPostParams, + { instanceName, orgName, projectName }: InstanceNetworkInterfacesPostParams, data: NetworkInterfaceCreate, params: RequestParams = {} ) => @@ -2836,11 +2783,7 @@ export class Api extends HttpClient { * Reboot an instance. */ projectInstancesInstanceReboot: ( - { - instanceName, - orgName, - projectName, - }: ProjectInstancesInstanceRebootParams, + { instanceName, orgName, projectName }: ProjectInstancesInstanceRebootParams, params: RequestParams = {} ) => this.request({ @@ -2853,11 +2796,7 @@ export class Api extends HttpClient { * Boot an instance. */ projectInstancesInstanceStart: ( - { - instanceName, - orgName, - projectName, - }: ProjectInstancesInstanceStartParams, + { instanceName, orgName, projectName }: ProjectInstancesInstanceStartParams, params: RequestParams = {} ) => this.request({ @@ -2870,11 +2809,7 @@ export class Api extends HttpClient { * Halt an instance. */ projectInstancesInstanceStop: ( - { - instanceName, - orgName, - projectName, - }: ProjectInstancesInstanceStopParams, + { instanceName, orgName, projectName }: ProjectInstancesInstanceStopParams, params: RequestParams = {} ) => this.request({ @@ -2929,11 +2864,7 @@ export class Api extends HttpClient { * Delete a snapshot from a project. */ projectSnapshotsDeleteSnapshot: ( - { - orgName, - projectName, - snapshotName, - }: ProjectSnapshotsDeleteSnapshotParams, + { orgName, projectName, snapshotName }: ProjectSnapshotsDeleteSnapshotParams, params: RequestParams = {} ) => this.request({ @@ -3101,12 +3032,7 @@ export class Api extends HttpClient { * Delete a router from its VPC */ vpcRoutersDeleteRouter: ( - { - orgName, - projectName, - routerName, - vpcName, - }: VpcRoutersDeleteRouterParams, + { orgName, projectName, routerName, vpcName }: VpcRoutersDeleteRouterParams, params: RequestParams = {} ) => this.request({ @@ -3119,13 +3045,7 @@ export class Api extends HttpClient { * List a Router's routes */ routersRoutesGet: ( - { - orgName, - projectName, - routerName, - vpcName, - ...query - }: RoutersRoutesGetParams, + { orgName, projectName, routerName, vpcName, ...query }: RoutersRoutesGetParams, params: RequestParams = {} ) => this.request({ @@ -3154,13 +3074,7 @@ export class Api extends HttpClient { * Get a VPC Router route */ routersRoutesGetRoute: ( - { - orgName, - projectName, - routeName, - routerName, - vpcName, - }: RoutersRoutesGetRouteParams, + { orgName, projectName, routeName, routerName, vpcName }: RoutersRoutesGetRouteParams, params: RequestParams = {} ) => this.request({ @@ -3173,13 +3087,7 @@ export class Api extends HttpClient { * Update a Router route */ routersRoutesPutRoute: ( - { - orgName, - projectName, - routeName, - routerName, - vpcName, - }: RoutersRoutesPutRouteParams, + { orgName, projectName, routeName, routerName, vpcName }: RoutersRoutesPutRouteParams, data: RouterRouteUpdateParams, params: RequestParams = {} ) => @@ -3270,12 +3178,7 @@ export class Api extends HttpClient { * Delete a subnet from a VPC. */ vpcSubnetsDeleteSubnet: ( - { - orgName, - projectName, - subnetName, - vpcName, - }: VpcSubnetsDeleteSubnetParams, + { orgName, projectName, subnetName, vpcName }: VpcSubnetsDeleteSubnetParams, params: RequestParams = {} ) => this.request({ @@ -3318,10 +3221,7 @@ export class Api extends HttpClient { /** * Fetch a specific built-in role */ - rolesGetRole: ( - { roleName }: RolesGetRoleParams, - params: RequestParams = {} - ) => + rolesGetRole: ({ roleName }: RolesGetRoleParams, params: RequestParams = {}) => this.request({ path: `/roles/${roleName}`, method: 'GET', @@ -3342,10 +3242,7 @@ export class Api extends HttpClient { /** * Fetch information about a single saga (for debugging) */ - sagasGetSaga: ( - { sagaId }: SagasGetSagaParams, - params: RequestParams = {} - ) => + sagasGetSaga: ({ sagaId }: SagasGetSagaParams, params: RequestParams = {}) => this.request({ path: `/sagas/${sagaId}`, method: 'GET', @@ -3373,11 +3270,7 @@ export class Api extends HttpClient { /** * Create a new silo. */ - silosPost: ( - query: SilosPostParams, - data: SiloCreate, - params: RequestParams = {} - ) => + silosPost: (query: SilosPostParams, data: SiloCreate, params: RequestParams = {}) => this.request({ path: `/silos`, method: 'POST', @@ -3388,10 +3281,7 @@ export class Api extends HttpClient { /** * Fetch a specific silo */ - silosGetSilo: ( - { siloName }: SilosGetSiloParams, - params: RequestParams = {} - ) => + silosGetSilo: ({ siloName }: SilosGetSiloParams, params: RequestParams = {}) => this.request({ path: `/silos/${siloName}`, method: 'GET', @@ -3401,10 +3291,7 @@ export class Api extends HttpClient { /** * Delete a specific silo. */ - silosDeleteSilo: ( - { siloName }: SilosDeleteSiloParams, - params: RequestParams = {} - ) => + silosDeleteSilo: ({ siloName }: SilosDeleteSiloParams, params: RequestParams = {}) => this.request({ path: `/silos/${siloName}`, method: 'DELETE', @@ -3414,10 +3301,7 @@ export class Api extends HttpClient { /** * List all timeseries schema */ - timeseriesSchemaGet: ( - query: TimeseriesSchemaGetParams, - params: RequestParams = {} - ) => + timeseriesSchemaGet: (query: TimeseriesSchemaGetParams, params: RequestParams = {}) => this.request({ path: `/timeseries/schema`, method: 'GET', @@ -3449,10 +3333,7 @@ export class Api extends HttpClient { /** * Fetch a specific built-in system user */ - usersGetUser: ( - { userName }: UsersGetUserParams, - params: RequestParams = {} - ) => + usersGetUser: ({ userName }: UsersGetUserParams, params: RequestParams = {}) => this.request({ path: `/users/${userName}`, method: 'GET', diff --git a/libs/api/__tests__/hooks.spec.ts b/libs/api/__tests__/hooks.spec.ts index 55056ee69c..f65dd8d82e 100644 --- a/libs/api/__tests__/hooks.spec.ts +++ b/libs/api/__tests__/hooks.spec.ts @@ -12,18 +12,13 @@ import { useApiQuery, useApiMutation } from '../' const config = { wrapper: Wrapper } -const renderGetOrgs = () => - renderHook(() => useApiQuery('organizationsGet', {}), config) +const renderGetOrgs = () => renderHook(() => useApiQuery('organizationsGet', {}), config) // 503 is a special key in the MSW server that returns a 503 const renderGetOrg503 = () => - renderHook( - () => useApiQuery('organizationsGetOrganization', { orgName: '503' }), - config - ) + renderHook(() => useApiQuery('organizationsGetOrganization', { orgName: '503' }), config) -const renderCreateOrg = () => - renderHook(() => useApiMutation('organizationsPost'), config) +const renderCreateOrg = () => renderHook(() => useApiMutation('organizationsPost'), config) const createParams = { body: { name: 'abc', description: '', hello: 'a' }, diff --git a/libs/api/__tests__/nav-to-login.ts b/libs/api/__tests__/nav-to-login.ts index ac7ad04f4a..ddbb8ec7e3 100644 --- a/libs/api/__tests__/nav-to-login.ts +++ b/libs/api/__tests__/nav-to-login.ts @@ -16,9 +16,7 @@ describe('loginUrl', () => { describe('includeCurrent = true', () => { it('includes state param', () => { window.history.pushState({}, '', '/abc/def') - expect(loginUrl({ includeCurrent: true })).toEqual( - '/login?state=%2Fabc%2Fdef' - ) + expect(loginUrl({ includeCurrent: true })).toEqual('/login?state=%2Fabc%2Fdef') }) it('includes query params from redirect url', () => { diff --git a/libs/api/__tests__/safety.spec.ts b/libs/api/__tests__/safety.spec.ts index 708a90964f..80bac9de70 100644 --- a/libs/api/__tests__/safety.spec.ts +++ b/libs/api/__tests__/safety.spec.ts @@ -4,10 +4,7 @@ import { execSync } from 'child_process' it('Generated API client version matches API version specified for deployment', () => { const generatedVersion = fs - .readFileSync( - path.resolve(__dirname, '../__generated__/OMICRON_VERSION'), - 'utf8' - ) + .readFileSync(path.resolve(__dirname, '../__generated__/OMICRON_VERSION'), 'utf8') .split('\n')[1] const packerConfig = fs.readFileSync( diff --git a/libs/api/hooks.ts b/libs/api/hooks.ts index 24b9949485..1f5c077191 100644 --- a/libs/api/hooks.ts +++ b/libs/api/hooks.ts @@ -15,10 +15,7 @@ export type Params = F extends (p: infer P, r: infer R) => any body?: R } : never -export type Result = F extends ( - p: any, - r: any -) => Promise> +export type Result = F extends (p: any, r: any) => Promise> ? R : never export type ResultItem = F extends ( diff --git a/libs/api/index.ts b/libs/api/index.ts index 060ab3fbb4..f89af0e360 100644 --- a/libs/api/index.ts +++ b/libs/api/index.ts @@ -1,9 +1,5 @@ import type { ResultItem } from './hooks' -import { - getUseApiMutation, - getUseApiQuery, - getUseApiQueryClient, -} from './hooks' +import { getUseApiMutation, getUseApiQuery, getUseApiQueryClient } from './hooks' import { Api } from './__generated__/Api' const api = new Api({ diff --git a/libs/api/nav-to-login.ts b/libs/api/nav-to-login.ts index 581b1bec6d..fda9ba49ea 100644 --- a/libs/api/nav-to-login.ts +++ b/libs/api/nav-to-login.ts @@ -1,9 +1,7 @@ // this is only a separate module so we can easily mock it in tests. jsdom // doesn't support navigation -export function loginUrl( - opts: { includeCurrent: boolean } = { includeCurrent: false } -) { +export function loginUrl(opts: { includeCurrent: boolean } = { includeCurrent: false }) { const { pathname, search } = window.location return opts.includeCurrent ? // TODO: include query args too? diff --git a/libs/api/util.ts b/libs/api/util.ts index ac53c1530c..65953c1d09 100644 --- a/libs/api/util.ts +++ b/libs/api/util.ts @@ -1,9 +1,5 @@ /// Helpers for working with API objects -import type { - IpNet, - VpcFirewallRule, - VpcFirewallRuleUpdate, -} from './__generated__/Api' +import type { IpNet, VpcFirewallRule, VpcFirewallRuleUpdate } from './__generated__/Api' import { pick } from '@oxide/util' type PortRange = [number, number] @@ -40,5 +36,4 @@ export const firewallRuleGetToPut = ( 'targets' ) -export const ipNetToStr = (ipNet: IpNet) => - 'V4' in ipNet ? ipNet.V4 : ipNet.V6 +export const ipNetToStr = (ipNet: IpNet) => ('V4' in ipNet ? ipNet.V4 : ipNet.V6) diff --git a/libs/babel-transform-react-display-name/index.js b/libs/babel-transform-react-display-name/index.js index be8d353c86..dc05835c9f 100644 --- a/libs/babel-transform-react-display-name/index.js +++ b/libs/babel-transform-react-display-name/index.js @@ -48,21 +48,16 @@ module.exports = function ({ types: t }) { } if (t.isFunctionDeclaration(componentFn) && componentFn.node.id) { - componentFn.insertAfter( - genDisplayName(path, componentFn.node.id.name) - ) + componentFn.insertAfter(genDisplayName(path, componentFn.node.id.name)) return } const isExpressionFn = - t.isFunctionExpression(componentFn) || - t.isArrowFunctionExpression(componentFn) + t.isFunctionExpression(componentFn) || t.isArrowFunctionExpression(componentFn) if (!isExpressionFn) return - const declarator = componentFn.findParent((path) => - t.isVariableDeclarator(path) - ) + const declarator = componentFn.findParent((path) => t.isVariableDeclarator(path)) if (declarator) { const parentStatement = componentFn.getStatementParent() const name = declarator.node.id.name @@ -78,10 +73,7 @@ module.exports = function ({ types: t }) { const leftHandSide = assignmentExpression.node.left // Only want to do this step for top level components - if ( - !t.isProgram(parentStatement.parent) || - !t.isMemberExpression(leftHandSide) - ) { + if (!t.isProgram(parentStatement.parent) || !t.isMemberExpression(leftHandSide)) { return } @@ -89,9 +81,7 @@ module.exports = function ({ types: t }) { t.assignmentExpression( '=', t.memberExpression(leftHandSide, t.identifier('displayName')), - t.stringLiteral( - `${printMemberExpression(leftHandSide)} - ${filePath(path)}` - ) + t.stringLiteral(`${printMemberExpression(leftHandSide)} - ${filePath(path)}`) ) ) return @@ -105,9 +95,7 @@ module.exports = function ({ types: t }) { if (t.isMemberExpression(path.node.tag)) { const memberString = printMemberExpression(path.node.tag) if (memberString.startsWith('classed.')) { - const declarator = path.findParent((path) => - t.isVariableDeclarator(path) - ) + const declarator = path.findParent((path) => t.isVariableDeclarator(path)) if (!declarator) return const parentStatement = path.getStatementParent() parentStatement.insertAfter( diff --git a/libs/form/Form.tsx b/libs/form/Form.tsx index 1241e6d72b..2b527e22a9 100644 --- a/libs/form/Form.tsx +++ b/libs/form/Form.tsx @@ -89,9 +89,7 @@ export function Form({ {cloneElement(actions, { formId: id, submitDisabled: - !props.dirty || - !props.isValid || - mutation.status === 'loading', + !props.dirty || !props.isValid || mutation.status === 'loading', onDismiss, })} @@ -101,9 +99,7 @@ export function Form({ {cloneElement(actions, { formId: id, submitDisabled: - !props.dirty || - !props.isValid || - mutation.status === 'loading', + !props.dirty || !props.isValid || mutation.status === 'loading', })} @@ -161,9 +157,7 @@ Form.Actions = ({ invariant(submit, 'Form.Actions must contain a Form.Submit component') return ( -
+
{cloneElement(submit, { form: formId, disabled: submitDisabled })} {isSideModal && cancel && cloneElement(cancel, { onClick: onDismiss })} {childArray} @@ -171,9 +165,7 @@ Form.Actions = ({ ) } -Form.Submit = (props: ButtonProps) => ( -
), - Cell: ({ row }: { row: Row }) => ( - - ), + Cell: ({ row }: { row: Row }) => , className: 'w-10', }) diff --git a/libs/table/headers/DefaultHeader.tsx b/libs/table/headers/DefaultHeader.tsx index dd9e34d8e5..95a80e425c 100644 --- a/libs/table/headers/DefaultHeader.tsx +++ b/libs/table/headers/DefaultHeader.tsx @@ -3,6 +3,4 @@ import React from 'react' interface DefaultHeaderProps { children: React.ReactNode } -export const DefaultHeader = ({ children }: DefaultHeaderProps) => ( - {children} -) +export const DefaultHeader = ({ children }: DefaultHeaderProps) => {children} diff --git a/libs/ui/.storybook/main.js b/libs/ui/.storybook/main.js index b8dcca6136..042622ca22 100644 --- a/libs/ui/.storybook/main.js +++ b/libs/ui/.storybook/main.js @@ -4,17 +4,12 @@ const tsBaseConfig = require('../../../tsconfig.json') process.env.IS_STORYBOOK = true -const findStoryPaths = ( - dir = path.join(__dirname, '../lib'), - knownStoryPaths = [] -) => { +const findStoryPaths = (dir = path.join(__dirname, '../lib'), knownStoryPaths = []) => { let files = fs.readdirSync(dir) files.forEach((file) => { let newDir = path.resolve(dir, file) - let storyPath = path.dirname( - path.relative(__dirname, path.resolve(dir, file)) - ) + let storyPath = path.dirname(path.relative(__dirname, path.resolve(dir, file))) if (fs.statSync(newDir).isDirectory()) { // eslint-disable-next-line no-param-reassign diff --git a/libs/ui/.storybook/webpack.config.js b/libs/ui/.storybook/webpack.config.js index cbb7629397..2ff88b85e2 100644 --- a/libs/ui/.storybook/webpack.config.js +++ b/libs/ui/.storybook/webpack.config.js @@ -6,9 +6,7 @@ const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin') */ module.exports = async ({ config }) => { const resolvePlugins = config.resolve.plugins || [] - resolvePlugins.push( - new TsconfigPathsPlugin({ configFile: './tsconfig.json' }) - ) + resolvePlugins.push(new TsconfigPathsPlugin({ configFile: './tsconfig.json' })) config.resolve.extensions.push('.mdx') config.resolve.plugins = resolvePlugins config.resolve.fallback = { @@ -21,8 +19,7 @@ module.exports = async ({ config }) => { const svgRule = config.module.rules.find((rule) => rule.test?.toString().startsWith('/\\.(svg|ico') ) - svgRule.test = - /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/ + svgRule.test = /\.(ico|jpg|jpeg|png|gif|eot|otf|webp|ttf|woff|woff2|cur|ani|pdf)(\?.*)?$/ config.module.rules.push({ test: /\.(png|jpe?g|gif|webp)$/, diff --git a/libs/ui/lib/action-menu/ActionMenu.tsx b/libs/ui/lib/action-menu/ActionMenu.tsx index 189c75408f..7cec33d148 100644 --- a/libs/ui/lib/action-menu/ActionMenu.tsx +++ b/libs/ui/lib/action-menu/ActionMenu.tsx @@ -152,10 +152,7 @@ export function ActionMenu(props: ActionMenuProps) { {label} {items.map((item) => ( -
+
{item.value === selectedItem?.value && } {/* @@ -189,10 +186,7 @@ export function ActionMenu(props: ActionMenuProps) {
- +
diff --git a/libs/ui/lib/badge/Badge.stories.tsx b/libs/ui/lib/badge/Badge.stories.tsx index 36f70f163a..0bb6db6e27 100644 --- a/libs/ui/lib/badge/Badge.stories.tsx +++ b/libs/ui/lib/badge/Badge.stories.tsx @@ -18,10 +18,7 @@ export const All = () => {
{Object.keys(colors).map((color) => (
- + {color}
diff --git a/libs/ui/lib/badge/Badge.tsx b/libs/ui/lib/badge/Badge.tsx index b49e71a7b5..58e623abe9 100644 --- a/libs/ui/lib/badge/Badge.tsx +++ b/libs/ui/lib/badge/Badge.tsx @@ -12,10 +12,7 @@ export interface BadgeProps { variant?: BadgeVariant } -export const badgeColors: Record< - BadgeVariant, - Partial> -> = { +export const badgeColors: Record>> = { default: { default: 'bg-accent text-inverse', destructive: 'bg-destructive text-inverse', @@ -30,8 +27,7 @@ export const badgeColors: Record< }, ghost: { default: 'ring-1 ring-inset ring-accent-secondary text-accent', - destructive: - 'ring-1 ring-inset ring-destructive-secondary text-destructive', + destructive: 'ring-1 ring-inset ring-destructive-secondary text-destructive', notice: 'ring-1 ring-inset ring-notice-secondary text-notice', }, } diff --git a/libs/ui/lib/bulk-action-menu/BulkActionMenu.tsx b/libs/ui/lib/bulk-action-menu/BulkActionMenu.tsx index 4b65512c9a..7bbc7e7407 100644 --- a/libs/ui/lib/bulk-action-menu/BulkActionMenu.tsx +++ b/libs/ui/lib/bulk-action-menu/BulkActionMenu.tsx @@ -9,20 +9,13 @@ export interface BulkActionMenuProps { onSelectAll: () => void } -export function BulkActionMenu({ - children, - selectedCount, -}: BulkActionMenuProps) { +export function BulkActionMenu({ children, selectedCount }: BulkActionMenuProps) { const actionButtons = flattenChildren(children) return (
-
- {actionButtons} -
+
{actionButtons}
- - {selectedCount} selected - + {selectedCount} selected
) diff --git a/libs/ui/lib/button/Button.tsx b/libs/ui/lib/button/Button.tsx index 25067b8e91..03541dff03 100644 --- a/libs/ui/lib/button/Button.tsx +++ b/libs/ui/lib/button/Button.tsx @@ -75,8 +75,7 @@ type ButtonStyleProps = { color?: Color } -export type ButtonProps = React.ComponentPropsWithRef<'button'> & - ButtonStyleProps +export type ButtonProps = React.ComponentPropsWithRef<'button'> & ButtonStyleProps export const buttonStyle = ({ size = 'base', diff --git a/libs/ui/lib/button/button.css b/libs/ui/lib/button/button.css index 7618142b02..24806f4a11 100644 --- a/libs/ui/lib/button/button.css +++ b/libs/ui/lib/button/button.css @@ -90,11 +90,5 @@ */ .btn-not-implemented { @apply cursor-not-allowed text-transparent focus:ring-transparent; - background: repeating-linear-gradient( - 45deg, - yellow, - yellow 10px, - black 10px, - black 20px - ); + background: repeating-linear-gradient(45deg, yellow, yellow 10px, black 10px, black 20px); } diff --git a/libs/ui/lib/checkbox/Checkbox.tsx b/libs/ui/lib/checkbox/Checkbox.tsx index db8bc456c0..ae61f2c9bd 100644 --- a/libs/ui/lib/checkbox/Checkbox.tsx +++ b/libs/ui/lib/checkbox/Checkbox.tsx @@ -52,9 +52,7 @@ export const Checkbox = ({ {indeterminate && } - {children && ( - {children} - )} + {children && {children}} ) diff --git a/libs/ui/lib/divider/Divider.tsx b/libs/ui/lib/divider/Divider.tsx index 6ce9c007cc..eb7d36d04d 100644 --- a/libs/ui/lib/divider/Divider.tsx +++ b/libs/ui/lib/divider/Divider.tsx @@ -5,9 +5,5 @@ export interface DividerProps { className?: string } export function Divider({ className }: DividerProps) { - return ( -
- ) + return
} diff --git a/libs/ui/lib/dropdown/Dropdown.tsx b/libs/ui/lib/dropdown/Dropdown.tsx index 78ee160ef0..ba5635707c 100644 --- a/libs/ui/lib/dropdown/Dropdown.tsx +++ b/libs/ui/lib/dropdown/Dropdown.tsx @@ -49,10 +49,7 @@ export const Dropdown: FC = ({ return (
- + {label}
    - + {children} {optional && ( // Announcing this optional text is unnecessary as the required attribute on the diff --git a/libs/ui/lib/multi-select/MultiSelect.tsx b/libs/ui/lib/multi-select/MultiSelect.tsx index c3995f022a..a58a34b03b 100644 --- a/libs/ui/lib/multi-select/MultiSelect.tsx +++ b/libs/ui/lib/multi-select/MultiSelect.tsx @@ -66,10 +66,7 @@ export const MultiSelect = ({ return (
    - + {label} diff --git a/libs/ui/lib/properties-table/PropertiesTable.stories.tsx b/libs/ui/lib/properties-table/PropertiesTable.stories.tsx index a54f649410..003f0fb3de 100644 --- a/libs/ui/lib/properties-table/PropertiesTable.stories.tsx +++ b/libs/ui/lib/properties-table/PropertiesTable.stories.tsx @@ -29,9 +29,7 @@ export const TwoColumnResponsive: Story = { Default network for the project - - frontend-production-vpn - + frontend-production-vpn diff --git a/libs/ui/lib/properties-table/PropertiesTable.tsx b/libs/ui/lib/properties-table/PropertiesTable.tsx index e30fe249fc..02fd1b85f8 100644 --- a/libs/ui/lib/properties-table/PropertiesTable.tsx +++ b/libs/ui/lib/properties-table/PropertiesTable.tsx @@ -37,9 +37,7 @@ PropertiesTable.Row = ({ label, children }: PropertiesTableRowProps) => ( {label} -
    - {children} -
    +
    {children}
    ) @@ -48,10 +46,7 @@ interface PropertiesTableGroupProps { className?: string } -PropertiesTable.Group = ({ - children, - className, -}: PropertiesTableGroupProps) => { +PropertiesTable.Group = ({ children, className }: PropertiesTableGroupProps) => { invariant( isOneOf(children, [PropertiesTable]), 'PropertiesTable can only have PropertiesTable as a child' diff --git a/libs/ui/lib/radio-group/RadioGroup.tsx b/libs/ui/lib/radio-group/RadioGroup.tsx index f645221e23..0daaa9e95e 100644 --- a/libs/ui/lib/radio-group/RadioGroup.tsx +++ b/libs/ui/lib/radio-group/RadioGroup.tsx @@ -72,11 +72,7 @@ export const RadioGroup = ({ onChange, }: RadioGroupProps) => (
    diff --git a/libs/ui/lib/radio/Radio.tsx b/libs/ui/lib/radio/Radio.tsx index 395542f181..1e3ff9cc9d 100644 --- a/libs/ui/lib/radio/Radio.tsx +++ b/libs/ui/lib/radio/Radio.tsx @@ -26,11 +26,7 @@ const fieldStyles = ` export const Radio = ({ children, className, ...inputProps }: RadioProps) => (
) diff --git a/libs/ui/lib/table/table.css b/libs/ui/lib/table/table.css index 63afd041a4..869c4af8c2 100644 --- a/libs/ui/lib/table/table.css +++ b/libs/ui/lib/table/table.css @@ -90,17 +90,11 @@ tr:last-of-type td:last-of-type { } /* Ensures subsequent, interior selections have side borders */ -.ox-table - .multi-selection:not(.selection-start):not(.selection-end) - td:first-child - > div { +.ox-table .multi-selection:not(.selection-start):not(.selection-end) td:first-child > div { box-shadow: -1px 0px var(--stroke-accent); } -.ox-table - .multi-selection:not(.selection-start):not(.selection-end) - td:last-child - > div { +.ox-table .multi-selection:not(.selection-start):not(.selection-end) td:last-child > div { box-shadow: 1px 0px var(--stroke-accent); } diff --git a/libs/ui/lib/tabs/Tabs.tsx b/libs/ui/lib/tabs/Tabs.tsx index 0c5dc1575c..b24a735f70 100644 --- a/libs/ui/lib/tabs/Tabs.tsx +++ b/libs/ui/lib/tabs/Tabs.tsx @@ -36,9 +36,7 @@ export function Tabs({ }: TabsProps) { const [tabs, panels] = useMemo(() => { const childArray = flattenChildren(children) - const tabs = pluckAllOfType(childArray, Tab).map( - addKey((i) => `${id}-tab-${i}`) - ) + const tabs = pluckAllOfType(childArray, Tab).map(addKey((i) => `${id}-tab-${i}`)) const panels = pluckAllOfType(childArray, Tab.Panel).map( addProps((i, panelProps) => ({ key: `${id}-panel-${i}`, @@ -86,9 +84,7 @@ export type TabProps = Assign & { name?: string } export function Tab({ className, ...props }: TabProps) { - return ( - - ) + return } export interface TabPanelProps extends RTabPanelProps { diff --git a/libs/ui/lib/tag/Tag.stories.tsx b/libs/ui/lib/tag/Tag.stories.tsx index 81c416ebde..459d102975 100644 --- a/libs/ui/lib/tag/Tag.stories.tsx +++ b/libs/ui/lib/tag/Tag.stories.tsx @@ -18,10 +18,7 @@ export const All = () => {
{Object.entries(tagColors).flatMap(([variant, colors], index) => Object.keys(colors).map((color) => ( - + {variant} {color} @@ -34,15 +31,8 @@ export const All = () => {
{Object.entries(tagColors).flatMap(([variant, colors], index) => Object.keys(colors).map((color) => ( - - + + {variant} {color} @@ -54,10 +44,7 @@ export const All = () => {
{Object.entries(tagColors).flatMap(([variant, colors], index) => Object.keys(colors).map((color) => ( - + {
{Object.entries(tagColors).flatMap(([variant, colors], index) => Object.keys(colors).map((color) => ( - + void } -export const tagColors: Record< - TagVariant, - Partial> -> = { +export const tagColors: Record>> = { default: { default: 'bg-accent text-inverse', destructive: 'bg-destructive text-inverse', @@ -54,10 +51,7 @@ export const Tag = ({ {onClose && ( )} diff --git a/libs/ui/lib/text-field/TextField.tsx b/libs/ui/lib/text-field/TextField.tsx index 284b3b0203..641dd1513e 100644 --- a/libs/ui/lib/text-field/TextField.tsx +++ b/libs/ui/lib/text-field/TextField.tsx @@ -81,11 +81,7 @@ export const TextFieldHint = ({ id, children, className }: HintProps) => ( export const TextFieldError = ({ name }: { name: string }) => (
- {(msg) => - msg && ( - {msg} - ) - } + {(msg) => msg && {msg}}
) diff --git a/libs/ui/lib/toast/Toast.tsx b/libs/ui/lib/toast/Toast.tsx index 8117b923b3..2c50e5b300 100644 --- a/libs/ui/lib/toast/Toast.tsx +++ b/libs/ui/lib/toast/Toast.tsx @@ -32,23 +32,14 @@ export const Toast = ({ timeout, variant = 'success', }: ToastProps) => ( - + {icon}
{title}
{content}
-