8000 Switch fully to generated types · coder/coder@60323d8 · GitHub
[go: up one dir, main page]

Skip to content

Commit 60323d8

Browse files
committed
Switch fully to generated types
In some places the organization ID is part of the URL but not part of the request so I separated out the ID into a separate argument in the relevant API functions. Otherwise this was a straightforward replacement where I mostly only needed to change some of the interface names (User instead of UserResponse for example) and add a few missing but required properties. Arguably `parameter_values` could be made optional but I am just passing in an empty array for now mostly just to make it obvious that we could pass stuff there if we need to. I kind of winged the template form; I am not sure what the difference between a template and template version is or why the latter comes before the former so the form just returns all the data required to create both.
1 parent d5eb87f commit 60323d8

File tree

22 files changed

+137
-115
lines changed
  • buildInfo
  • terminal
  • users
  • workspace
  • 22 files changed

    +137
    -115
    lines changed

    site/src/api/index.test.ts

    Lines changed: 3 additions & 3 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,6 +1,6 @@
    11
    import axios from "axios"
    22
    import { getApiKey, login, logout } from "."
    3-
    import { APIKeyResponse, LoginResponse } from "./types"
    3+
    import * as TypesGen from "./typesGenerated"
    44

    55
    // Mock the axios module so that no real network requests are made, but rather
    66
    // we swap in a resolved or rejected value
    @@ -12,7 +12,7 @@ describe("api.ts", () => {
    1212
    describe("login", () => {
    1313
    it("should return LoginResponse", async () => {
    1414
    // given
    15-
    const loginResponse: LoginResponse = {
    15+
    const loginResponse: TypesGen.LoginWithPasswordResponse = {
    1616
    session_token: "abc_123_test",
    1717
    }
    1818
    const axiosMockPost = jest.fn().mockImplementationOnce(() => {
    @@ -87,7 +87,7 @@ describe("api.ts", () => {
    8787
    describe("getApiKey", () => {
    8888
    it("should return APIKeyResponse", async () => {
    8989
    // given
    90-
    const apiKeyResponse: APIKeyResponse = {
    90+
    const apiKeyResponse: TypesGen.GenerateAPIKeyResponse = {
    9191
    key: "abc_123_test",
    9292
    }
    9393
    const axiosMockPost = jest.fn().mockImplementationOnce(() => {

    site/src/api/index.ts

    Lines changed: 38 additions & 27 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,26 +1,32 @@
    11
    import axios, { AxiosRequestHeaders } from "axios"
    22
    import { mutate } from "swr"
    3-
    import * as Types from "./types"
    43
    import * as TypesGen from "./typesGenerated"
    54

    65
    const CONTENT_TYPE_JSON: AxiosRequestHeaders = {
    76
    "Content-Type": "application/json",
    87
    }
    98

    10-
    export const provisioners: Types.Provisioner[] = [
    9+
    export const provisioners: TypesGen.ProvisionerDaemon[] = [
    1110
    {
    1211
    id: "terraform",
    1312
    name: "Terraform",
    13+
    created_at: "",
    14+
    provisioners: [],
    1415
    },
    1516
    {
    1617
    id: "cdr-basic",
    1718
    name: "Basic",
    19+
    created_at: "",
    20+
    provisioners: [],
    1821
    },
    1922
    ]
    2023

    2124
    export namespace Workspace {
    22-
    export const create = async (request: Types.CreateWorkspaceRequest): Promise<Types.Workspace> => {
    23-
    const response = await fetch(`/api/v2/organizations/${request.organization_id}/workspaces`, {
    25+
    export const create = async (
    26+
    organizationId: string,
    27+
    request: TypesGen.CreateWorkspaceRequest,
    28+
    ): Promise<TypesGen.Workspace> => {
    29+
    const response = await fetch(`/api/v2/organizations/${organizationId}/workspaces`, {
    2430
    method: "POST",
    2531
    headers: {
    2632
    "Content-Type": "application/json",
    @@ -43,13 +49,13 @@ export namespace Workspace {
    4349
    }
    4450
    }
    4551

    46-
    export const login = async (email: string, password: string): Promise<Types.LoginResponse> => {
    52+
    export const login = async (email: string, password: string): Promise<TypesGen.LoginWithPasswordResponse> => {
    4753
    const payload = JSON.stringify({
    4854
    email,
    4955
    password,
    5056
    })
    5157

    52-
    const response = await axios.post<Types.LoginResponse>("/api/v2/users/login", payload, {
    58+
    const response = await axios.post<TypesGen.LoginWithPasswordResponse>("/api/v2/users/login", payload, {
    5359
    headers: { ...CONTENT_TYPE_JSON },
    5460
    })
    5561

    @@ -60,8 +66,8 @@ export const logout = async (): Promise<void> => {
    6066
    await axios.post("/api/v2/users/logout")
    6167
    }
    6268

    63-
    export const getUser = async (): Promise<Types.UserResponse> => {
    64-
    const response = await axios.get<Types.UserResponse>("/api/v2/users/me")
    69+
    export const getUser = async (): Promise<TypesGen.User> => {
    70+
    const response = await axios.get<TypesGen.User>("/api/v2/users/me")
    6571
    return response.data
    6672
    }
    6773

    @@ -70,8 +76,8 @@ export const getAuthMethods = async (): Promise<TypesGen.AuthMethods> => {
    7076
    return response.data
    7177
    }
    7278

    73-
    export const getApiKey = async (): Promise<Types.APIKeyResponse> => {
    74-
    const response = await axios.post<Types.APIKeyResponse>("/api/v2/users/me/keys")
    79+
    export const getApiKey = async (): Promise<TypesGen.GenerateAPIKeyResponse> => {
    80+
    const response = await axios.post<TypesGen.GenerateAPIKeyResponse>("/api/v2/users/me/keys")
    7581
    return response.data
    7682
    }
    7783

    @@ -80,55 +86,57 @@ export const getUsers = async (): Promise<TypesGen.User[]> => {
    8086
    return response.data
    8187
    }
    8288

    83-
    export const getOrganization = async (organizationId: string): Promise<Types.Organization> => {
    84-
    const response = await axios.get<Types.Organization>(`/api/v2/organizations/${organizationId}`)
    89+
    export const getOrganization = async (organizationId: string): Promise<TypesGen.Organization> => {
    90+
    const response = await axios.get<TypesGen.Organization>(`/api/v2/organizations/${organizationId}`)
    8591
    return response.data
    8692
    }
    8793

    88-
    export const getOrganizations = async (): Promise<Types.Organization[]> => {
    89-
    const response = await axios.get<Types.Organization[]>("/api/v2/users/me/organizations")
    94+
    export const getOrganizations = async (): Promise<TypesGen.Organization[]> => {
    95+
    const response = await axios.get<TypesGen.Organization[]>("/api/v2/users/me/organizations")
    9096
    return response.data
    9197
    }
    9298

    93-
    export const getTemplate = async (templateId: string): Promise<Types.Template> => {
    94-
    const response = await axios.get<Types.Template>(`/api/v2/templates/${templateId}`)
    99+
    export const getTemplate = async (templateId: string): Promise<TypesGen.Template> => {
    100+
    const response = await axios.get<TypesGen.Template>(`/api/v2/templates/${templateId}`)
    95101
    return response.data
    96102
    }
    97103

    98-
    export const getWorkspace = async (workspaceId: string): Promise<Types.Workspace> => {
    99-
    const response = await axios.get<Types.Workspace>(`/api/v2/workspaces/${workspaceId}`)
    104+
    export const getWorkspace = async (workspaceId: string): Promise<TypesGen.Workspace> => {
    105+
    const response = await axios.get<TypesGen.Workspace>(`/api/v2/workspaces/${workspaceId}`)
    100106
    return response.data
    101107
    }
    102108

    103109
    export const getWorkspaceByOwnerAndName = async (
    104110
    organizationID: string,
    105111
    username = "me",
    106112
    workspaceName: string,
    107-
    ): Promise<Types.Workspace> => {
    108-
    const response = await axios.get<Types.Workspace>(
    113+
    ): Promise<TypesGen.Workspace> => {
    114+
    const response = await axios.get<TypesGen.Workspace>(
    109115
    `/api/v2/organizations/${organizationID}/workspaces/${username}/${workspaceName}`,
    110116
    )
    111117
    return response.data
    112118
    }
    113119

    114-
    export const getWorkspaceResources = async (workspaceBuildID: string): Promise<Types.WorkspaceResource[]> => {
    115-
    const response = await axios.get<Types.WorkspaceResource[]>(`/api/v2/workspacebuilds/${workspaceBuildID}/resources`)
    120+
    export const getWorkspaceResources = async (workspaceBuildID: string): Promise<TypesGen.WorkspaceResource[]> => {
    121+
    const response = await axios.get<TypesGen.WorkspaceResource[]>(
    122+
    `/api/v2/workspacebuilds/${workspaceBuildID}/resources`,
    123+
    )
    116124
    return response.data
    117125
    }
    118126

    119-
    export const createUser = async (user: Types.CreateUserRequest): Promise<TypesGen.User> => {
    127+
    export const createUser = async (user: TypesGen.CreateUserRequest): Promise<TypesGen.User> => {
    120128
    const response = await axios.post<TypesGen.User>("/api/v2/users", user)
    121129
    return response.data
    122130
    }
    123131

    124-
    export const getBuildInfo = async (): Promise<Types.BuildInfoResponse> => {
    132+
    export const getBuildInfo = async (): Promise<TypesGen.BuildInfoResponse> => {
    125133
    const response = await axios.get("/api/v2/buildinfo")
    126134
    return response.data
    127135
    }
    128136

    129137
    export const putWorkspaceAutostart = async (
    130138
    workspaceID: string,
    131-
    autostart: Types.WorkspaceAutostartRequest,
    139+
    autostart: TypesGen.UpdateWorkspaceAutostartRequest,
    132140
    ): Promise<void> => {
    133141
    const payload = JSON.stringify(autostart)
    134142
    await axios.put(`/api/v2/workspaces/${workspaceID}/autostart`, payload, {
    @@ -138,15 +146,18 @@ export const putWorkspaceAutostart = async (
    138146

    139147
    export const putWorkspaceAutostop = async (
    140148
    workspaceID: string,
    141-
    autostop: Types.WorkspaceAutostopRequest,
    149+
    autostop: TypesGen.UpdateWorkspaceAutostopRequest,
    142150
    ): Promise<void> => {
    143151
    const payload = JSON.stringify(autostop)
    144152
    await axios.put(`/api/v2/workspaces/${workspaceID}/autostop`, payload, {
    145153
    headers: { ...CONTENT_TYPE_JSON },
    146154
    })
    147155
    }
    148156

    149-
    export const updateProfile = async (userId: string, data: Types.UpdateProfileRequest): Promise<Types.UserResponse> => {
    157+
    export const updateProfile = async (
    158+
    userId: string,
    159+
    data: TypesGen.UpdateUserProfileRequest,
    160+
    ): Promise<TypesGen.User> => {
    150161
    const response = await axios.put(`/api/v2/users/${userId}/profile`, data)
    151162
    return response.data
    152163
    }

    site/src/components/CreateUserForm/CreateUserForm.tsx

    Lines changed: 5 additions & 5 deletions
    Original file line numberDiff line numberDiff line change
    @@ -3,7 +3,7 @@ import TextField from "@material-ui/core/TextField"
    33
    import { FormikContextType, FormikErrors, useFormik } from "formik"
    44
    import React from "react"
    55
    import * as Yup from "yup"
    6-
    import { CreateUserRequest } from "../../api/types"
    6+
    import * as TypesGen from "../../api/typesGenerated"
    77
    import { getFormHelpers, onChangeTrimmed } from "../../util/formUtils"
    88
    import { FormFooter } from "../FormFooter/FormFooter"
    99
    import { FullPageForm } from "../FullPageForm/FullPageForm"
    @@ -21,9 +21,9 @@ export const Language = {
    2121
    }
    2222

    2323
    export interface CreateUserFormProps {
    24-
    onSubmit: (user: CreateUserRequest) => void
    24+
    onSubmit: (user: TypesGen.CreateUserRequest) => void
    2525
    onCancel: () => void
    26-
    formErrors?: FormikErrors<CreateUserRequest>
    26+
    formErrors?: FormikErrors<TypesGen.CreateUserRequest>
    2727
    isLoading: boolean
    2828
    error?: string
    2929
    myOrgId: string
    @@ -43,7 +43,7 @@ export const CreateUserForm: React.FC<CreateUserFormProps> = ({
    4343
    error,
    4444
    myOrgId,
    4545
    }) => {
    46-
    const form: FormikContextType<CreateUserRequest> = useFormik<CreateUserRequest>({
    46+
    const form: FormikContextType<TypesGen.CreateUserRequest> = useFormik<TypesGen.CreateUserRequest>({
    4747
    initialValues: {
    4848
    email: "",
    4949
    password: "",
    @@ -53,7 +53,7 @@ export const CreateUserForm: React.FC<CreateUserFormProps> = ({
    5353
    validationSchema,
    5454
    onSubmit,
    5555
    })
    56-
    const getFieldHelpers = getFormHelpers<CreateUserRequest>(form, formErrors)
    56+
    const getFieldHelpers = getFormHelpers<TypesGen.CreateUserRequest>(form, formErrors)
    5757

    5858
    return (
    5959
    <FullPageForm title="Create user" onCancel={onCancel}>

    site/src/components/Footer/Footer.tsx

    Lines changed: 2 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -3,11 +3,11 @@ import { makeStyles } from "@material-ui/core/styles"
    33
    import Typography from "@material-ui/core/Typography"
    44
    import { useActor } from "@xstate/react"
    55
    import React, { useContext } from "react"
    6-
    import { BuildInfoResponse } from "../../api/types"
    6+
    import * as TypesGen from "../../api/typesGenerated"
    77
    import { XServiceContext } from "../../xServices/StateContext"
    88

    99
    export const Language = {
    10-
    buildInfoText: (buildInfo: BuildInfoResponse): string => {
    10+
    buildInfoText: (buildInfo: TypesGen.BuildInfoResponse): string => {
    1111
    return `Coder ${buildInfo.version}`
    1212
    },
    1313
    }

    site/src/components/NavbarView/NavbarView.tsx

    Lines changed: 2 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -3,14 +3,14 @@ import ListItem from "@material-ui/core/ListItem"
    33
    import { fade, makeStyles } from "@material-ui/core/styles"
    44
    import React from "react"
    55
    import { NavLink } from "react-router-dom"
    6-
    import { UserResponse } from "../../api/types"
    6+
    import * as TypesGen from "../../api/typesGenerated"
    77
    import { navHeight } from "../../theme/constants"
    88
    import { AdminDropdown } from "../AdminDropdown/AdminDropdown"
    99
    import { Logo } from "../Icons/Logo"
    1010
    import { UserDropdown } from "../UserDropdown/UsersDropdown"
    1111

    1212
    export interface NavbarViewProps {
    13-
    user?: UserResponse
    13+
    user?: TypesGen.User
    1414
    onSignOut: () => void
    1515
    }
    1616

    site/src/components/UserDropdown/UsersDropdown.tsx

    Lines changed: 2 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -7,7 +7,7 @@ import { fade, makeStyles } from "@material-ui/core/styles"
    77
    import AccountIcon from "@material-ui/icons/AccountCircleOutlined"
    88
    import React, { useState } from "react"
    99
    import { Link } from "react-router-dom"
    10-
    import { UserResponse } from "../../api/types"
    10+
    import * as TypesGen from "../../api/typesGenerated"
    1111
    import { BorderedMenu } from "../BorderedMenu/BorderedMenu"
    1212
    import { CloseDropdown, OpenDropdown } from "../DropdownArrows/DropdownArrows"
    1313
    import { DocsIcon } from "../Icons/DocsIcon"
    @@ -21,7 +21,7 @@ export const Language = {
    2121
    signOutLabel: "Sign Out",
    2222
    }
    2323
    export interface UserDropdownProps {
    24-
    user: UserResponse
    24+
    user: TypesGen.User
    2525
    onSignOut: () => void
    2626
    }
    2727

    site/src/components/UserProfileCard/UserProfileCard.tsx

    Lines changed: 2 additions & 2 deletions
    Original file line numberDiff line numberDiff line change
    @@ -1,11 +1,11 @@
    11
    import { makeStyles } from "@material-ui/core/styles"
    22
    import Typography from "@material-ui/core/Typography"
    33
    import React from "react"
    4-
    import { UserResponse } from "../../api/types"
    4+
    import * as TypesGen from "../../api/typesGenerated"
    55
    import { UserAvatar } from "../UserAvatar/UserAvatar"
    66

    77
    interface UserProfileCardProps {
    8-
    user: UserResponse
    8+
    user: TypesGen.User
    99
    }
    1010

    1111
    export const UserProfileCard: React.FC<UserProfileCardProps> = ({ user }) => {

    site/src/components/UsersTable/UsersTable.tsx

    Lines changed: 4 additions & 5 deletions
    Original file line numberDiff line numberDiff line change
    @@ -5,7 +5,6 @@ import TableCell from "@material-ui/core/TableCell"
    55
    import TableHead from "@material-ui/core/TableHead"
    66
    import TableRow from "@material-ui/core/TableRow"
    77
    import React from "react"
    8-
    import { UserResponse } from "../../api/types"
    98
    import * as TypesGen from "../../api/typesGenerated"
    109
    import { EmptyState } from "../EmptyState/EmptyState"
    1110
    import { RoleSelect } from "../RoleSelect/RoleSelect"
    @@ -25,10 +24,10 @@ export const Language = {
    2524
    }
    2625

    2726
    export interface UsersTableProps {
    28-
    users: UserResponse[]
    29-
    onSuspendUser: (user: UserResponse) => void
    30-
    onResetUserPassword: (user: UserResponse) => void
    31-
    onUpdateUserRoles: (user: UserResponse, roles: TypesGen.Role["name"][]) => void
    27+
    users: TypesGen.User[]
    28+
    onSuspendUser: (user: TypesGen.User) => void
    29+
    onResetUserPassword: (user: TypesGen.User) => void
    30+
    onUpdateUserRoles: (user: TypesGen.User, roles: TypesGen.Role["name"][]) => void
    3231
    roles: TypesGen.Role[]
    3332
    isUpdatingUserRoles?: boolean
    3433
    }

    site/src/components/Workspace/Workspace.tsx

    Lines changed: 4 additions & 4 deletions
    Original file line numberDiff line numberDiff line change
    @@ -5,15 +5,15 @@ import Typography from "@material-ui/core/Typography"
    55
    import CloudCircleIcon from "@material-ui/icons/CloudCircle"
    66
    import React from "react"
    77
    import { Link } from "react-router-dom"
    8-
    import * as Types from "../../api/types"
    8+
    import * as TypesGen from "../../api/typesGenerated"
    99
    import { WorkspaceSchedule } from "../WorkspaceSchedule/WorkspaceSchedule"
    1010
    import { WorkspaceSection } from "../WorkspaceSection/WorkspaceSection"
    1111
    import * as Constants from "./constants"
    1212

    1313
    export interface WorkspaceProps {
    14-
    organization: Types.Organization
    15-
    workspace: Types.Workspace
    16-
    template: Types.Template
    14+
    organization: TypesGen.Organization
    15+
    workspace: TypesGen.Workspace
    16+
    template: TypesGen.Template
    1717
    }
    1818

    1919
    /**

    site/src/forms/CreateTemplateForm.tsx

    Lines changed: 20 additions & 6 deletions
    Original file line numberDiff line numberDiff line change
    @@ -3,7 +3,7 @@ import { makeStyles } from "@material-ui/core/styles"
    33
    import { FormikContextType, useFormik } from "formik"
    44
    import React from "react"
    55
    import * as Yup from "yup"
    6-
    import { CreateTemplateRequest, Organization, Provisioner, Template } from "../api/types"
    6+
    import * as TypesGen from "../api/typesGenerated"
    77
    import { FormCloseButton } from "../components/FormCloseButton/FormCloseButton"
    88
    import { FormDropdownField, FormDropdownItem } from "../components/FormDropdownField/FormDropdownField"
    99
    import { FormSection } from "../components/FormSection/FormSection"
    @@ -12,13 +12,21 @@ import { FormTitle } from "../components/FormTitle/FormTitle"
    1212
    import { LoadingButton } from "../components/LoadingButton/LoadingButton"
    1313
    import { maxWidth } from "../theme/constants"
    1414

    15+
    // It appears that to create a template you need to create a template version
    16+
    // and then a template so this contains the information to do both.
    17+
    export type CreateTemplateRequest = TypesGen.CreateTemplateVersionRequest & Pick<TypesGen.CreateTemplateRequest, "name">
    18+
    1519
    export interface CreateTemplateFormProps {
    16-
    provisioners: Provisioner[]
    17-
    organizations: Organization[]
    18-
    onSubmit: (request: CreateTemplateRequest) => Promise<Template>
    20+
    provisioners: TypesGen.ProvisionerDaemon[]
    21+
    organizations: TypesGen.Organization[]
    22+
    onSubmit: (organizationId: string, request: CreateTemplateRequest) => Promise<TypesGen.Template>
    1923
    onCancel: () => void
    2024
    }
    2125

    26+
    interface CreateTemplateFields extends Pick<CreateTemplateRequest, "name" | "provisioner"> {
    27+
    organizationId: string
    28+
    }
    29+
    2230
    const validationSchema = Yup.object({
    2331
    provisioner: Yup.string().required("Provisioner is required."),
    2432
    organizationId: Yup.string().required("Organization is required."),
    @@ -33,7 +41,7 @@ export const CreateTemplateForm: React.FC<CreateTemplateFormProps> = ({
    3341
    }) => {
    3442
    const styles = useStyles()
    3543

    36-
    const form: FormikContextType<CreateTemplateRequest> = useFormik<CreateTemplateRequest>({
    44+
    const form: FormikContextType<CreateTemplateFields> = useFormik<CreateTemplateFields>({
    3745
    initialValues: {
    3846
    provisioner: provisioners[0].id,
    3947
    organizationId: organizations[0].name,
    @@ -42,7 +50,13 @@ export const CreateTemplateForm: React.FC<CreateTemplateFormProps> = ({
    4250
    enableReinitialize: true,
    4351
    validationSchema: validationSchema,
    4452
    onSubmit: (req) => {
    45-
    return onSubmit(req)
    53+
    return onSubmit(req.organizationId, {
    54+
    name: req.name,
    55+
    storage_method: "file",
    56+
    storage_source: "hash",
    57+
    provisioner: req.provisioner,
    58+
    parameter_values: [],
    59+
    })
    4660
    },
    4761
    })
    4862

    0 commit comments

    Comments
     (0)
    0