From 2abbc1ca07440e4c8e4511510e16686202bcee64 Mon Sep 17 00:00:00 2001 From: Presley Pizzo Date: Fri, 9 Sep 2022 00:33:39 +0000 Subject: [PATCH 1/2] Turn predictable action arguments on --- site/src/xServices/audit/auditXService.ts | 3 +- site/src/xServices/auth/authXService.ts | 19 +- .../xServices/buildInfo/buildInfoXService.ts | 3 +- .../createWorkspaceXService.ts | 5 +- .../entitlements/entitlementsXService.ts | 5 +- site/src/xServices/roles/siteRolesXService.ts | 5 +- site/src/xServices/setup/setupXService.ts | 3 +- .../xServices/template/templateXService.ts | 3 +- .../templateSettingsXService.ts | 7 +- .../xServices/templates/templatesXService.ts | 171 +-- .../xServices/terminal/terminalXService.ts | 3 +- site/src/xServices/users/usersXService.ts | 3 +- .../xServices/workspace/workspaceXService.ts | 1014 +++++++++-------- .../workspaceBuild/workspaceBuildXService.ts | 3 +- .../workspaceScheduleBannerXService.ts | 3 +- .../workspaceScheduleXService.ts | 3 +- .../workspaces/workspacesXService.ts | 4 +- 17 files changed, 683 insertions(+), 574 deletions(-) diff --git a/site/src/xServices/audit/auditXService.ts b/site/src/xServices/audit/auditXService.ts index b26fcb1313583..2ab414900d79b 100644 --- a/site/src/xServices/audit/auditXService.ts +++ b/site/src/xServices/audit/auditXService.ts @@ -7,6 +7,8 @@ import { assign, createMachine } from "xstate" export const auditMachine = createMachine( { id: "auditMachine", + predictableActionArguments: true, + tsTypes: {} as import("./auditXService.typegen").Typegen0, schema: { context: {} as { auditLogs?: AuditLog[]; count?: number; page: number; limit: number }, services: {} as { @@ -29,7 +31,6 @@ export const auditMachine = createMachine( page: number }, }, - tsTypes: {} as import("./auditXService.typegen").Typegen0, initial: "loading", states: { loading: { diff --git a/site/src/xServices/auth/authXService.ts b/site/src/xServices/auth/authXService.ts index d3c0a27ab2bd2..b90d0d7321b97 100644 --- a/site/src/xServices/auth/authXService.ts +++ b/site/src/xServices/auth/authXService.ts @@ -91,14 +91,8 @@ export const authMachine = /** @xstate-layout N4IgpgJg5mDOIC5QEMCuAXAFgZXc9YAdLAJZQB2kA8hgMTYCSA4gHID6DLioADgPal0JPuW4gAHogBsATimEAzDIAcAFgUB2VTJ26ANCACeiAIwaADKsLKFtu-dsBfRwbRZc+IqQolyUBuS0ECJEvgBufADWXmTkAWL8gsKiSBKICubKhKpSyhoArAbGCGaqGoRSlVXVlfnOrhg4eATEsb7+gWAATl18XYQ8ADb4AGZ9ALatFPGpiSRCImKSCLLySmqa2ro6RaYFAEzWDscK9SBuTZ6EMOhCfgCqsN1BIYThUUQ3ALJgCQLzySW6Uy2VyBV2JXyUhMFRqcLqLnOjQ8LRudygj2e3V6-SGowm1zA6B+fySi1Sy32MnyhHyyksYK2ug0EJM1IURxO9jOFxRnyJ6IACt1xiRYKQRLAXpQ3uQItFCABjTBgRWRYVdUXi5LwWb-BYpUDLZRScygvKFIyIGQaQ4FHnI5r827tDVaiXkKXYvoDYboMaapUqtVusUe3W8fWAimIE1mnIW1l0rImOE1BENdxOwkuvw-LB8CBS4Iy94K75EzCFiMgOYGoEIZRUwgyVT5BQmfaW4omGxZGxcuwOrNXNHtfNVou0b24v0ByYVgtF0kA8lG2PN1vtzvd0zszmD06I3nZ7yUCABAa9EYkQahCB32j3QUAEQAggAVACibEFACUqAAMQYAAZL8V3rGMSjbGQKihLsISkOlaWHS4WjPSBLx4a9byIVAeAgfBXRwx8S1COUPkIE8rgwi9yCvPgbzvQh8MIoUSLABB3kVIiRAAbXMABdCDo3XaD8lgpCpAQq0EA0eTUL5KZzywjiWIIoi-EFDjpx6H08X9AlqPQ2JMPo7DGNw9S2OIyy7y4iieINAThL1MlDTScTJPg3dGxkfZFNPUy6OIWBMDeB8wFoJgvw-NhsGwAAJNgAGkvwATREtdPM7VQrE0XyTF7coB0PQKaOCy9xXCsc-ASxKUrAQxpXI+UiGMmIKDM0KaoFdp6sawwHIiJzkhcrKPOWIqkOscFZNTfYOXtY9HQqrqQuqnN0QGprdJxX18UDDrlO6zbaqgHahu43jyHGtzV0m0x9jyxQ5p7ExzBhUrB3Kkz1qqsLCEGPhkAgSAIsfP8vxilgvz-T8f3q1KMomht9g+8ocnMGQCtZDRZAPLkMyREc-pU+jNuB0HwcVEQb01S6-zAGBKC6TxaAAYTfFgOa-EC2ChmG4YR+KkuRzL7sgsT0bMQhzCUcxpMK20vsPBRieO2iAfCqmwYgJU6ZIBmksGpmWe6dmOaoFhgL-L4Behr9Yfh79ReStKJcjdy0Yx0Fsdx+b23MX7OvJnqgZBvXCC6ZmwFZzSLpN3ayNlNqqNWsnTsB3XwZj822e2pOrscm67q9h6GzMBQrDy7cZJ7DR1ZQlbSdDrOdcj3PY-jwuGt2mcDsMo6M7bjbs87-W87ji3e8G4a+FG-ihNRqCq5rtsO3r0wpG0ZvMzQ0eqtVVAunmQwIai5931d7Avw5+4-wYD9PdrKNsqmsoOQyBM3sQZ6pBDidDax9T7oHPqxBO2AQFnxaqnSimtKoU2gWA6ykDkHFxGqXZektRI5U-ooBkiZZIKFyHvEmB8gFH0VCfM+qDtroL2vpOcRkR6UKQdQ0B4CNL0I4Wfeei9brYPLlLPBjcCE-18m2KwGtWFa0CIwVgbAqD3A-CvaWWgYSEN-iUDIZpUxpiqBoQBZ52g0HQLAssoczFqM8k2WCW5N6+X2OYeShMTgyNbspUxdAB4GXnMpaxOD35-w0XLCRrJ0ZWH0QYqQRiW4UOVKqSI7RAJG1gOgTEXQLEUQVMdRJaoUlpIyU8Lo-CsGuWEbg5YmhCD7B3nU-YA5lA6HVhCZxYjoRshyDvJQ+NVCAIAO7IABH4QCfQPwqlSV0dJmT6DMHYJwGx1Sm7Yx0I3SwziTBOLqWaLQdIpC2HyKoLZ5gESInIIWOAYgEHrUCZU4JJRsY0iIT2akZoPEUJMX4GY9zHoIDbIcdGLzt4qFhDEpCgDzqZKWYgVQ+xWSyCyOC2okK+paRFGGHUML-mmnNNorZbIwUxI+Upc6E5qzYq2LUuQwKSitnymrI8+8lJyIYkxe8zELlfj0l0bFVcaRlCklvRspzjGILZVZEgkVCAzj5Y3AV+MfIQjyEy8hLLxUWXZRfOVRVsiKqVhCRuhxtgaBVY3A5MgxX-XMmpCB7E7K-CCX8oq+RnnaIKJa+J6rrUSrvHykwHZZq+X2bScwYbzUSTUBCr1QUfWbSlX6p1lctlusKp2Q4JLY1hzOmixOfdii-MrlIiotKPpyCtdm8e1N9YJsdYWqCmyshyH9vigoVhkWxIre3CO1aDbkHpuMRm3cZ51tft7BtqhzAZoVga+aGhexuOOJmtalaO69qnj3fqRc+UKHpIQIq87S25GXZnMea69Y7qhPuswxVCptnKNsOQ7Z2xUhPYfCmYV-WBtLVOjkJqzUkP6TGldp10EX0IFynlcroRywsI4iEu6ArAdPVQmhKDa0yqg0m1e+NNFwZ3BCNswdkPvuIGB2tcqakuPlgR4h2MWzMgAxartwDeEoLtf1dB-rXVBoQyQljqHOFfq+q2v9jHG7mqUKqm55N-UuN4-NT6DGdD5C0Gp-Ypq31eL8HcsdFcG0yA+rB5QtHijOKOYoNWgD8nJNGUU6F2GxK9LlvSTIcLGn5C2ZUNpLj5CxIUFSD6XmuyDOGeiMZXQJlgCmTMkp2LGm1OUFCHQORGkyEVqoZQbTNly2-poaERy6kh0pYl5LrZpLNIy1l2Sm5dAkPRs4wz+NlDOGcEAA */ createMachine( { - context: { - me: undefined, - getUserError: undefined, - authError: undefined, - updateProfileError: undefined, - methods: undefined, - getMethodsError: undefined, - }, + id: "authState", + predictableActionArguments: true, tsTypes: {} as import("./authXService.typegen").Typegen0, schema: { context: {} as AuthContext, @@ -133,7 +127,14 @@ export const authMachine = } }, }, - id: "authState", + context: { + me: undefined, + getUserError: undefined, + authError: undefined, + updateProfileError: undefined, + methods: undefined, + getMethodsError: undefined, + }, initial: "gettingUser", states: { signedOut: { diff --git a/site/src/xServices/buildInfo/buildInfoXService.ts b/site/src/xServices/buildInfo/buildInfoXService.ts index f5cfc8bf7ac45..56948865012fa 100644 --- a/site/src/xServices/buildInfo/buildInfoXService.ts +++ b/site/src/xServices/buildInfo/buildInfoXService.ts @@ -9,6 +9,8 @@ export interface BuildInfoContext { export const buildInfoMachine = createMachine( { + id: "buildInfoState", + predictableActionArguments: true, tsTypes: {} as import("./buildInfoXService.typegen").Typegen0, schema: { context: {} as BuildInfoContext, @@ -21,7 +23,6 @@ export const buildInfoMachine = createMachine( context: { buildInfo: undefined, }, - id: "buildInfoState", initial: "gettingBuildInfo", states: { gettingBuildInfo: { diff --git a/site/src/xServices/createWorkspace/createWorkspaceXService.ts b/site/src/xServices/createWorkspace/createWorkspaceXService.ts index ec679731036f1..a63605852183f 100644 --- a/site/src/xServices/createWorkspace/createWorkspaceXService.ts +++ b/site/src/xServices/createWorkspace/createWorkspaceXService.ts @@ -28,7 +28,8 @@ type CreateWorkspaceEvent = { export const createWorkspaceMachine = createMachine( { id: "createWorkspaceState", - initial: "gettingTemplates", + predictableActionArguments: true, + tsTypes: {} as import("./createWorkspaceXService.typegen").Typegen0, schema: { context: {} as CreateWorkspaceContext, events: {} as CreateWorkspaceEvent, @@ -44,7 +45,7 @@ export const createWorkspaceMachine = createMachine( } }, }, - tsTypes: {} as import("./createWorkspaceXService.typegen").Typegen0, + initial: "gettingTemplates", states: { gettingTemplates: { entry: "clearGetTemplatesError", diff --git a/site/src/xServices/entitlements/entitlementsXService.ts b/site/src/xServices/entitlements/entitlementsXService.ts index 0da90acd79237..3eee8a5e43ac6 100644 --- a/site/src/xServices/entitlements/entitlementsXService.ts +++ b/site/src/xServices/entitlements/entitlementsXService.ts @@ -28,7 +28,8 @@ const emptyEntitlements = { export const entitlementsMachine = createMachine( { id: "entitlementsMachine", - initial: "idle", + predictableActionArguments: true, + tsTypes: {} as import("./entitlementsXService.typegen").Typegen0, schema: { context: {} as EntitlementsContext, events: {} as EntitlementsEvent, @@ -38,10 +39,10 @@ export const entitlementsMachine = createMachine( }, }, }, - tsTypes: {} as import("./entitlementsXService.typegen").Typegen0, context: { entitlements: emptyEntitlements, }, + initial: "idle", states: { idle: { on: { diff --git a/site/src/xServices/roles/siteRolesXService.ts b/site/src/xServices/roles/siteRolesXService.ts index ee9eaa47d8198..0f100be2d85f1 100644 --- a/site/src/xServices/roles/siteRolesXService.ts +++ b/site/src/xServices/roles/siteRolesXService.ts @@ -19,7 +19,8 @@ type SiteRolesEvent = { export const siteRolesMachine = createMachine( { id: "siteRolesState", - initial: "idle", + predictableActionArguments: true, + tsTypes: {} as import("./siteRolesXService.typegen").Typegen0, schema: { context: {} as SiteRolesContext, events: {} as SiteRolesEvent, @@ -29,7 +30,7 @@ export const siteRolesMachine = createMachine( }, }, }, - tsTypes: {} as import("./siteRolesXService.typegen").Typegen0, + initial: "idle", states: { idle: { on: { diff --git a/site/src/xServices/setup/setupXService.ts b/site/src/xServices/setup/setupXService.ts index 564d1fb6b9d14..4d02c0b5b376b 100644 --- a/site/src/xServices/setup/setupXService.ts +++ b/site/src/xServices/setup/setupXService.ts @@ -26,6 +26,8 @@ export const setupMachine = /** @xstate-layout N4IgpgJg5mDOIC5QGUwBcCuAHZaCGaYAdAJYQA2YAxAMIBKAogIIAqDA+gGICSdyL7AKrIGdRKCwB7WCTQlJAO3EgAHogDMAViKaAnPoDsABgBMRgCy6jpkwBoQAT0QBGI+qIA2N0ePOAHJqa-qYAviH2qJg4+IREAMYATmAEJApQnCQJsGiCsGAJVBCKxKkAbpIA1sSJyYQZWTl5CcpSMnKKymoI6ibuzmZGuiYG6kYemn4eHvZOCObOzjom-X7qHsZGmuq6mmER6Ni4BNVJKWn12bn5VPkJkglEWOQEAGb3ALbxp3WZl00t0lk8iUSFUGl07g8-XMxlWmmsWnUMxcUyIzg86hhPgWvg8JjC4RACkkEDgykihxiJQoYABbWBnUQflcRAMZlc6jWwwMfmRCDM2ksfgMzl0Bisbj85j8exAFOixy+tVS6V+jXydKBHVBXQAtDsiOyeVp-OoFrpnHyzboiKZ1CMDCNzEY-H4xbL5UdYi81VcEjRvpBNe0QaAuoEbZzpfaRh4rFM+eYTOZbcsTBD0b0bB6DgrCMGGTrELrzYajM5jUFVubLY4NIsvKM2eMtKZNOMCSEgA */ createMachine( { + id: "SetupState", + predictableActionArguments: true, tsTypes: {} as import("./setupXService.typegen").Typegen0, schema: { context: {} as SetupContext, @@ -36,7 +38,6 @@ export const setupMachine = } }, }, - id: "SetupState", initial: "idle", states: { idle: { diff --git a/site/src/xServices/template/templateXService.ts b/site/src/xServices/template/templateXService.ts index d9944d382ed4b..992b9edb3716d 100644 --- a/site/src/xServices/template/templateXService.ts +++ b/site/src/xServices/template/templateXService.ts @@ -33,6 +33,8 @@ export const templateMachine = /** @xstate-layout N4IgpgJg5mDOIC5QAoC2BDAxgCwJYDswBKAOhgBdyCoAVMVABwBt1ywBiCAe0JIIDcuAazAk0WPIVIUq+WvWaswCAV0ytcPANoAGALqJQDLrFxUehkAA9EAJgDsOkgGZbO2wE5bANg8BGABZnHR0AgBoQAE9EPx0-Eg9EpIAOe28-D28ggF9siPEcAmI+fDNcdCYASXwAMy4SLCp+MDpGFjYANTAAJ1MeMjBKagBBTCaWhXawLt7NfE4eUVURMQxCqRKyiuq6hrHcZtbFTp6+-AGhuVHxo6mZs5V8QXVzfF0DJBBjU1fLGwQAgF4t4AKzeWzOTIhEEhZIRaIIZI6EEkEIhZyg2xuEF+XL5NaSYoELZVWr1NhtJQAJTgXAArt1MHALrJ5JS2DTYPTGXAFrxlqICoTSMSqNsySQKccwJzuUzYCzqLdqbSGfLHs8NNp9JZvmULJ9-kDkiRks4QR50SDkh5nH5nPCYjpXKi0SDnObbeaAniQEKiiLSmLSbspXdTnMFTIlZMlPdI3ylk9hIKCQHNsGduTYydZjwo4NWcrc2dYBq1Fq3jrPnrfobEAFQqbQt5kiCcf4go6ECD7Ca0XFMskAmksr7-RtReUQ1xEyRYOQlKsJOmp+K6rqTPr8H9ELaTclkg5wQEzRidB5u-Y0q6QgFbAEsuCMuO0xsmFx0BBIOwACIAUQAGX-Gh-03H45ksBFrycGE7zcW1bD8e0In+Pw3G8EggT8M0-Fbc8PGSV8Vw2TAeBqXBulQahfzAJhBg4ABhAB5AA5AAxSoqQAWQAfQA4DQPA7ddwQZCMVRUF7Bw3svXsEFuz8MFMNtC8bRtHQzWHYj1mKMjako6i5Fo+i2HYRjhlYxigP4oCQLAmstzrUA0OcaSSHsZwbSUjwAl83zwiiGJGw8LCwTtU8vGQnI8j9N9im-UzqDnAUSEShjizAYTnOsRB7BHEglLwoqskCWxFJ8ewPJ0bx8tsC1IQhZwdOFNK6MGZKem6LhuhIY46iotrTImdkssciCDRcvcbVRJrwr8fLXHsRTYRIOCau8WqYRxIjfXwLhv3gT4J2KaM5Ey7LIPrAFyqChBLVvEJPGk2w21PFrVyDacsz2G4c2mCN+jOqBrgOEbpXjSavicq6prEhar1tR7IXSaSfVik7AxJH7GjBzLIfOWA6UweUjqMGGof+TzbEKsEMiRdwYUhbtkhw5HnHvXx0g8D7Jy+9d6lxw5-oJy7Kb3B07vsJDkekjwcSyWxeaJfmZ0lf7ZTVZlgcyzWeTJ6GJp3a7kOWu7YjcR6wQCEFAQfbxlaxzMJTDFUuS1hUiZJuADdrWHcoQVtMJxdtWfvaL0hWm2rfcRXHxBR2M2+l2NdVfWxeNuHbW7Xz+xCWJkm8ZE3LbRO1zV12S0jRVzpFwH8F9inM4D03u2Ux6sWvQj2wTjH4qd5PQzrvMG-nYnSYz0TQRNG3gnUyE+zNNv-EevDrUya9mr7kiVexlPRoJxujdE7O7r8gIO+dXtUkyMvVazSfrt8bt7xpgcFttC1nXsROPy-SBH5w1iO6MKwRghAkbH2BSUtHBrTRPeC8rhxKJ30hRKiNF2psEAS3ZCNMkR4R8MOWqfloEIntCvDmnoRzyUIvLRO6VWTYP+F4TCNt0g22REhV6pCYgEJIPVDENsPBpA9GkehmCAHjREtdVmmFPCKy2u6RwcJzaQicMOb0wQ3ALVxNvXSRAmExBUWQvOA5baqXlrbXIuQgA */ createMachine( { + id: "templateMachine", + predictableActionArguments: true, tsTypes: {} as import("./templateXService.typegen").Typegen0, schema: { context: {} as TemplateContext, @@ -58,7 +60,6 @@ export const templateMachine = } }, }, - id: "(machine)", initial: "gettingTemplate", states: { gettingTemplate: { diff --git a/site/src/xServices/templateSettings/templateSettingsXService.ts b/site/src/xServices/templateSettings/templateSettingsXService.ts index de80fbcedc842..d0fce5d9b4ee0 100644 --- a/site/src/xServices/templateSettings/templateSettingsXService.ts +++ b/site/src/xServices/templateSettings/templateSettingsXService.ts @@ -7,7 +7,9 @@ export const templateSettingsMachine = /** @xstate-layout N4IgpgJg5mDOIC5QBcwFsAOAbAhqgymMsgJYB2UsAdFgPY4TlQDEEtZYV5AbrQNadUmXASKkK1OgyYIetAMZ4S7ANoAGALqJQGWrBKl22kAA9EANgCMVAKwB2AByWATJbWWAnABYv55w-MAGhAAT0RnAGZnKgibGw9nD3M1JJsHNQiAX0zgoWw8MEJiJmpIAyZmfABBADUAUWNdfUMyYzMESx9bSK8IhwdncwcbF2dgsIRejypzX2dXf09zCLUbbNz0fNFiiSpYHG4Ktg4uMl4BKjyRQrESvYOZOUUW9S0kECbyo3f25KoHOxeDwODx9EYeNTzcYWGxqKgeGw+SJ2cx+VZebI5EBkWgQODGK4FIriSg0eiMCiNPRfVo-RBeMahRAQqhqNnuWERFFeOyedYgQnbEmlRgkqnNZS00DtSwRcz-EY2PzeeYOLk2aEIWJ2WwOIEBNIeBG8-mCm47Un7Q6U96fFptenWRJDIZy+y9AFBJkIEbRbxeWUBRwIyx2U2ba7Eu5WyDimkOhAI2yxSx+foMpWWTV2RLJgIrPoA4bh4RE24SOP2ukdHXOgJq8zuvoozWWBys9nzSydNt2NQYzFAA */ createMachine( { - initial: "loading", + id: "templateSettings", + predictableActionArguments: true, + tsTypes: {} as import("./templateSettingsXService.typegen").Typegen0, schema: {} as { context: { organizationId: string @@ -26,7 +28,7 @@ export const templateSettingsMachine = } events: { type: "SAVE"; templateSettings: UpdateTemplateMeta } }, - tsTypes: {} as import("./templateSettingsXService.typegen").Typegen0, + initial: "loading", states: { loading: { invoke: { @@ -71,7 +73,6 @@ export const templateSettingsMachine = type: "final", }, }, - id: "templateSettings", }, { services: { diff --git a/site/src/xServices/templates/templatesXService.ts b/site/src/xServices/templates/templatesXService.ts index 68e7a847e9fb7..9b0d9484cf71b 100644 --- a/site/src/xServices/templates/templatesXService.ts +++ b/site/src/xServices/templates/templatesXService.ts @@ -11,94 +11,101 @@ interface TemplatesContext { templatesError?: Error | unknown } -export const templatesMachine = createMachine( - { - tsTypes: {} as import("./templatesXService.typegen").Typegen0, - schema: { - context: {} as TemplatesContext, - services: {} as { - getOrganizations: { - data: TypesGen.Organization[] - } - getPermissions: { - data: boolean - } - getTemplates: { - data: TypesGen.Template[] - } - }, - }, - id: "templatesState", - initial: "gettingOrganizations", - states: { - gettingOrganizations: { - entry: "clearOrganizationsError", - invoke: { - src: "getOrganizations", - id: "getOrganizations", - onDone: [ - { - actions: ["assignOrganizations", "clearOrganizationsError"], - target: "gettingTemplates", - }, - ], - onError: [ - { - actions: "assignOrganizationsError", - target: "error", - }, - ], +export const templatesMachine = + /** @xstate-layout N4IgpgJg5mDOIC5QBcwFsAOAbAhq2AysnmAHQzLICWAdlAPIBOUONVAXnlQPY2wDEEXmVoA3bgGsyFJizadqveEhAZusKopqJQAD0QAWAMwHSATgDsANgCsNgzeuOATABoQAT0QBGb89I2AAzB3oEAHH7eFtFhAL6x7qiYuPhEJORglLQMzKwcXEr8YIyM3Iyk2HgAZmVoGciyeQo8fDqq6potbfoIxqaWtvaOthZunogmRgHBgc4Wvs5mYbPxieiVqcSo9dR0ACrrKXCCwqRiktKZB8kkyqBqGlrdPsH9Zs6+VlZhxlbOBu4vAgzIFSDNgot5s4wnZViAkhs4GlthRdlBroiBMVSuUNjVGHUKBijnd2o8uioeqFAm8Pt4vj8jH8AeMEM5AjYwTMouEDGEzPTnPEEiAaNwIHA2giScjLlk6I15AVWioHp1eM9emMgb4zNMZh8wvMzH8LHDpbdZTtssTbm01U9KYgvqDmUsIt4+TYIoDECbzGZA2Y+lYjIEjIHzYdLVsyEIaGB7R1HXofOyLKQDIsrKELAYogKjL6EL4wlyZjCswYHBEozdNulsWUk+SNU6S+nM9nc-mLIXi845qQjCOjDZg3YwjC65jZS31dp294wsXl8LYkA */ + createMachine( + { + id: "templatesState", + predictableActionArguments: true, + tsTypes: {} as import("./templatesXService.typegen").Typegen0, + schema: { + context: {} as TemplatesContext, + services: {} as { + getOrganizations: { + data: TypesGen.Organization[] + } + getPermissions: { + data: boolean + } + getTemplates: { + data: TypesGen.Template[] + } }, - tags: "loading", }, - gettingTemplates: { - entry: "clearTemplatesError", - invoke: { - src: "getTemplates", - id: "getTemplates", - onDone: { - target: "done", - actions: ["assignTemplates", "clearTemplatesError"], + initial: "gettingOrganizations", + states: { + gettingOrganizations: { + entry: "clearOrganizationsError", + invoke: { + src: "getOrganizations", + id: "getOrganizations", + onDone: [ + { + actions: ["assignOrganizations", "clearOrganizationsError"], + target: "gettingTemplates", + }, + ], + onError: [ + { + actions: "assignOrganizationsError", + target: "error", + }, + ], }, - onError: { - target: "error", - actions: "assignTemplatesError", + tags: "loading", + }, + gettingTemplates: { + entry: "clearTemplatesError", + invoke: { + src: "getTemplates", + id: "getTemplates", + onDone: [ + { + actions: ["assignTemplates", "clearTemplatesError"], + target: "done", + }, + ], + onError: [ + { + actions: "assignTemplatesError", + target: "error", + }, + ], }, + tags: "loading", }, - tags: "loading", + done: {}, + error: {}, }, - done: {}, - error: {}, }, - }, - { - actions: { - assignOrganizations: assign({ - organizations: (_, event) => event.data, - }), - assignOrganizationsError: assign({ - organizationsError: (_, event) => event.data, - }), - clearOrganizationsError: assign((context) => ({ - ...context, - organizationsError: undefined, - })), - assignTemplates: assign({ - templates: (_, event) => event.data, - }), - assignTemplatesError: assign({ - templatesError: (_, event) => event.data, - }), - clearTemplatesError: (context) => assign({ ...context, getWorkspacesError: undefined }), - }, - services: { - getOrganizations: API.getOrganizations, - getTemplates: async (context) => { - if (!context.organizations || context.organizations.length === 0) { - throw new Error("no organizations") - } - return API.getTemplates(context.organizations[0].id) + { + actions: { + assignOrganizations: assign({ + organizations: (_, event) => event.data, + }), + assignOrganizationsError: assign({ + organizationsError: (_, event) => event.data, + }), + clearOrganizationsError: assign((context) => ({ + ...context, + organizationsError: undefined, + })), + assignTemplates: assign({ + templates: (_, event) => event.data, + }), + assignTemplatesError: assign({ + templatesError: (_, event) => event.data, + }), + clearTemplatesError: (context) => assign({ ...context, getWorkspacesError: undefined }), + }, + services: { + getOrganizations: API.getOrganizations, + getTemplates: async (context) => { + if (!context.organizations || context.organizations.length === 0) { + throw new Error("no organizations") + } + return API.getTemplates(context.organizations[0].id) + }, }, }, - }, -) + ) diff --git a/site/src/xServices/terminal/terminalXService.ts b/site/src/xServices/terminal/terminalXService.ts index 3bc57cc0ba8c9..392aaa503f052 100644 --- a/site/src/xServices/terminal/terminalXService.ts +++ b/site/src/xServices/terminal/terminalXService.ts @@ -36,6 +36,8 @@ export const terminalMachine = /** @xstate-layout N4IgpgJg5mDOIC5QBcwCcC2BLAdgQwBsBlZPVAOhmWVygHk0o8csAvMrAex1gGIJuYcrgBunANZCqDJi3Y1u8JCAAOnWFgU5EoAB6IA7AE4AzOSMBGAEwBWCyYAsANgs2bVgDQgAnohNGbcgsnEIcHCwAOBwAGCKMHAF8Er1RMXEISMikwaloZZjYORV50NE40chUCMgAzcoxKHPy5Ip4dVXVNLm1lfQQIiLMIpxMbQYjYo2jXL18EawtyAwGwk1HTMdGklPRsfGJSCioaHCgAdXLxWBU8AGMwfkFhHDFJRuQLtCub+-a1DS07T69icVnILisDhspiccQ2sz8y3INmiqNGsMcBmiNm2IFSewyh2yuVOn2+dwepXKlWqyDqmHeZOuFL+nUBvUQILBEKhMLhowRCAMTkCIzWDkcEyMBhsBlx+PSByy7xO50uzPuAEEYDhkI8cEJRBJiUyfmBtWBdayAd0gZyjCFyFZbKjnC4jKYLIK7GYYqirCYBk5olYDIlknjdorMkccqrTRSLbqSmgyhUqrV6oz1Wak8hrV1uHb5g6nE6XdE3RYPSYvT5EWCA2s7E4sbZhfKo-sY0JbtwDbdVfrDS9jeQ+zgB-nlP9Cz09IhIcLyCZIUYotEDCZNxEDN7peY1ms4gYrNNBp20t2ieP+2BB7QU2maZmGROpwX2QuEEuy6uHOuMRbjue71ggdiLPY4phiYMoWNYl4EkqFDvveqAQLwZwAEoAJIACoAKKfraHI-gYkTkCGAFYmG0TbnWcw2A4YKmGskJno44RWIh0Y3qhg6QLwWEEZqAAixFFqRobViusKngYMpWEGgpQmWUFsSEcSOHRPHXsq-Hobwok4UQADCdAAHIWQRpl4RJ84gH0SmtuQDgTNWMJTDKJgqUEq4RNCljTOs3ERgqekUBAWCwAZgnmVZNl2TObIkd+zplrEYanvY0SwrCESCs6BiuaidGrgGTgekYSQRjgnAQHA7ThYSyrHHkjAFPI3RKKAs5fo5iAxIEXHMSMErWNiTiFa4K6ldi1ayu4FjhjsV4tbGJJql8GpgPZxYWNMDiubBdh2Ju7pGIK-jFW6rYiq4bZOLp63EvGOaJjq069Slknfq4jrOii51udiMpXbC5ATKi1ghNEljNs9yG9neD6nHtUlnhErmgqeIyosKazejNZ7+qMi3BiYiM9rek5oZA6NpeR0ROmGpgnhT0qCmNSxHhKW4BiGERUzeUUxSj6EMwN4HM5ukLLXBViRKGNhXVj64etM0JOG5YTC1kktORlp7hA4CtK2DYEALQQ8M5FKQd27OJTNVAA */ createMachine( { + id: "terminalState", + predictableActionArguments: true, tsTypes: {} as import("./terminalXService.typegen").Typegen0, schema: { context: {} as TerminalContext, @@ -52,7 +54,6 @@ export const terminalMachine = } }, }, - id: "terminalState", initial: "gettingWorkspace", states: { gettingWorkspace: { diff --git a/site/src/xServices/users/usersXService.ts b/site/src/xServices/users/usersXService.ts index 4d22c9534771a..8bd01931ea2ba 100644 --- a/site/src/xServices/users/usersXService.ts +++ b/site/src/xServices/users/usersXService.ts @@ -70,6 +70,8 @@ export type UsersEvent = export const usersMachine = createMachine( { + id: "usersState", + predictableActionArguments: true, tsTypes: {} as import("./usersXService.typegen").Typegen0, schema: { context: {} as UsersContext, @@ -95,7 +97,6 @@ export const usersMachine = createMachine( } }, }, - id: "usersState", initial: "idle", states: { idle: { diff --git a/site/src/xServices/workspace/workspaceXService.ts b/site/src/xServices/workspace/workspaceXService.ts index 67d5bfa6674cb..88ac29ff029a0 100644 --- a/site/src/xServices/workspace/workspaceXService.ts +++ b/site/src/xServices/workspace/workspaceXService.ts @@ -79,291 +79,372 @@ const permissionsToCheck = (workspace: TypesGen.Workspace) => ({ }, }) -export const workspaceMachine = createMachine( - { - tsTypes: {} as import("./workspaceXService.typegen").Typegen0, - schema: { - context: {} as WorkspaceContext, - events: {} as WorkspaceEvent, - services: {} as { - getWorkspace: { - data: TypesGen.Workspace - } - getTemplate: { - data: TypesGen.Template - } - startWorkspace: { - data: TypesGen.WorkspaceBuild - } - stopWorkspace: { - data: TypesGen.WorkspaceBuild - } - deleteWorkspace: { - data: TypesGen.WorkspaceBuild - } - cancelWorkspace: { - data: Types.Message - } - refreshWorkspace: { - data: TypesGen.Workspace | undefined - } - getResources: { - data: TypesGen.WorkspaceResource[] - } - getBuilds: { - data: TypesGen.WorkspaceBuild[] - } - loadMoreBuilds: { - data: TypesGen.WorkspaceBuild[] - } - checkPermissions: { - data: TypesGen.UserAuthorizationResponse - } - }, - }, - id: "workspaceState", - initial: "idle", - on: { - GET_WORKSPACE: "gettingWorkspace", - }, - states: { - idle: { - tags: "loading", - }, - gettingWorkspace: { - entry: ["clearGetWorkspaceError", "clearContext"], - invoke: { - src: "getWorkspace", - id: "getWorkspace", - onDone: { - target: "refreshingTemplate", - actions: ["assignWorkspace"], - }, - onError: { - target: "error", - actions: "assignGetWorkspaceError", - }, +export const workspaceMachine = + /** @xstate-layout N4IgpgJg5mDOIC5QHcD2AnA1rADgQwGMwBlAFz1LADoZTSBLAOygHUNt8iBiCVR6pgDdUmarTZZchMIlA5Usegz6yQAD0QAWAAwAmKgHYAbAFYjADgDMB80YCcu87oA0IAJ6JLARhP6Dly01dO1tzAztTAF9I1zRJThJyShowOiZWdiluMHR0DCocABsKADMMAFsU0gkOaVV5RWVGVQ0EOwMvQxNw7VsHbU1Nc1cPBEtgy0MAoIcTE20vI0to2MyEsgpqdDAS7dgAC3SAFTByos2ePgFGYVEqbd24fZOz4sp6hSV6FSR1LT1DKYLNY+o4XO5EI4DH5prpfHYAgYViA4rUiBtkg89odmC9zpQuDk8ugCm8yuhKlinni3jJfg0vj9QK0dH4gVYbPYwSNPNprFNAroDNptAYOl4kTEUWtpBixKkGMwAAo5cr0WCKPiwS78KhCETUAj7MAETAqinqzWMeD0z5NFqILx6fQWAwmOzzfzmII8hCLTSTIxB8USyxGLzLKWorKJTZVRVQc1qjXfa2E3L5fHkypGk1m1WW1M2uR21MOv3Oqiu92eyze8GjRx2OxUXSw0yaIxw8zI6PrJJbMB4CBuAqoQqFdI1GP3HbYqcy7i8XX6u5Ug7ThIfRpl36tUOTbQI8wDMxeHxGX0dcxUEUirwRJ29Nu9xexzFDkdjicL+LSWePAcv5omA6bEqSpQVAB2KbnUto7kyfx+v4h7Hqe4YXr6Sz6Heei9NYRhBJor5-uiA6zsOo7yD+zCwUQVDIHgXzMFwaiwOReAlJQ6AABRPtoACUXB9rK5HbJR36TrRb4MUxCbboyzR7o65gmJorZ8hKHQdJY2hzL6Jjered4RuYXi2JoEYkSBcoUV+ABGACu9CFBAeoQIUoHEEcACCABKRwKfaykILoR7aLeXZzIE4yqZoBi+hGenGSKgzaEGdh6SY1kxrZ4kOc5rnuZ5XDeQA8kqQW7sykLhZFcImDFjhqQlEKhboXj6AEgTpeeekSsRUZvnln6jk5LlufQHmgT5xAANIAPoACIAKIADIrUcK1VYhrRhZl9XRQGzXxYlAwGClAznuK3p2Dl-ZxvlY2FZN01cAAqkqS0+VtO1KTVoV1elDVNXFrWjANRiXUGFhmeG92iY9o1UONRVTSVADCPkAHIY+tf3lvtEXA0dsUtYlhmHneZgniebqDaspHvoOEmo25eCwJg6RLWAnkEqtG2-fBimE7ouhQ2YcJ2BK5hme0l5tR6nS4UKEbeE4d1DUzI2sy9VAc1zzA83zoFY7j63Letm3bcLwUAx1RgRR1R4RHYllOhKvrNi2uGBD4HXegjZFI7rE2zgAjo5cAJhs6CkDq1y3NQ7F4HHdF0iWCH-UhQomJ04bQnpEwB4lqk3t1Oi6Z2miekHzN2c9YfbJH0fpLH8dEpmZJQSnadvgTIW5+pEqu7Y8wim7iVePFVDjwMst8hERh1zrBVN2ALfsW3pCoDgCd6jcBpUOxu-pwP9udfoedmEYxidYRnttftF0V3yuiaG74zL1rNlicjbMRyjlvZgZBd5gS7pBCkx8d44DPrbaqOdOomFvDYRYR57DHXBrVc8VBX6DGMM2SMjNf4hzXkVZuQCEzG1SKBZcicj4QF5jQuBmcRYhQlGLKsZMlhBCDJ2CmhlcHdQRDYBYNciHSm1n-UO5CN6UO5kwgkncSRZigowk2LCQAMjtkhDhLpuGCj4QrCG8UurCPHmKPSEiRLBw-DItyFDW7MAxngRgRBCj71XIaVx7jNHaIQXtOqVhHaWBvtfMwiUAw+zvB-MugQlgr2kWQhxcinFQBcW43m4CVHdygQQHxvM-Gll2pCJ0N53R1mnldEIdhEqhKpiKPOvR3TpWyj-XKSTG6yMAjiKANILh0IPknaC1JTj4gzlo4p2c9oGBnt4OEEpF6NXaIlYUyDX5hm0sYRJpCukpJ6ccMZtJskQVINmEZBx+nvHgSUwGB0SaNWOmDRKSxlZ3iWE4YUxhJTEI6bsyS6Q-JwFQI5dARBYDxkBcC0F4LPGHzuLQIFsAQVgrgOfXRFhOjvzbD4XopjjC+jrMTEyfJvTmUajsuxX5qJSSgEilF4LIXMHpTCuAJzVFQMRdC1FxZJlZ3LIsMyrYgjeHmN6aEBKn5u0uueDCsy1IM0kSQqlVFxy0pZTy2SzEoCsRTskTi3EeJzyEjY+uT0AXMu5Yyxi2r0X7jFFi8y5gIgBFUosSwvp35Q1wqeBwsyAxtN+Q9FVVAGDlF5kweUaRmAACEXrakGV4hiw1OmhvoOGqSUaExxomrABA+p8lNAANraAALp2sdLFW8x4P7iLmA2SElgERUCsH7PQbsF4-KVX8kNYaI26loNm+N7LcmVFNavUcfbM1MqgDm1yeaC0UFTCW8tNzpmVscNWustbGr1sJRGKGFcxaVNsLoSlLMvxTsjVQQoqBhyQDnRACF6NQJrTKj5JaC0ACyZU-IrQWjG96ABJNaS1iAVuQr0Ks15vmEVmV4T1jsWwV2njFWV38g2I17em-t1Bb33ogI+59b0-0ADE-3EAABILSOEBr960gPYxtqwnRgTGpUAlOZJtstOqy09f6ltsJRQRmFGe9pwaL2Tpw9O-DjDCPxpvXeiA6Qv0YDAERuFwzx2pqvbqWTD6FOyZU2poj+bD6FuXWWiDiwPQcfCB0AYEQ5iGU9SeZDsIwxHiCGJzDtjJNpozde-T8nc2KeHMZ7YGnlGnPOdp-5um8NKYM6FozzBVORfjWZ4QFm+Arus-YZBI8HMf1MHMYYT9oSTCPUMMMIQfPdok1QZRXAADim0FosF-XNYgSofJ4wg+0ToboeiggGEMQl79kEoW822R2PhA0Naw6BNrRwOtdZ6315jfK2EAx9G1AITpWywjzt4fw3RohSkYKgRhvK4vJBfRBvbowAgWCO01XF-gu13azcBGMEHwxO00mEMMnUwwmAmz4WewZb5+sIhS8TS2Lm9KuRM-xtynu8nfgKAMnGWkInPTOpMhYtT-c4dWQicsTzg6flYCK039oM4w4tvzDcLUZCZkj37W410CvVlu26dbfBYQ-rPO8wQP7dk7AT81NKuf-htfJHn7CQgXRsJlR8YpVLGMQBTy678RFWBfAjlnMu1Vy6INZ8X-Od2hKF21POOETJ1kakKaE0v-56we0rgGD485Q7hKyewftqcQ26BdOecwPnYvd-Y-WnMFEmwg22OZSDwwIgfPUs6ukugigIuGCwNcY-JMAWk9uSeVdHaiXTd+7rS4iiET1MWrT2g9mN2aj369N4xxgUnwIL9U8Z4z41T1SVBM9VmdLXw78i97JL8AqA1DrksYCZW8y1u3a7rtyYptY+m3BAn44axKb-kAMcfPjJ7je8p7hGn7wCJh9tWnmYUXIoljzF8KpL7x+Q2n7nE8Q5rwmwvejsuCmUt8syz85kLyboDeOg7qzqzYM+KML0lu0qR426G+tuDaCAYQ0S94Yo8q08revm7eEksulqyKrKEKg6UKlBPK1mfO6BAum+2Boql0ooD86utgSB5BdKVqcAWqiuy+tyD4UGRW0sCIuchE+6xK7y6sryR+Ui-yvBGq4KqB6kTBNue6j+syl0sUoowQ4sSBCWxUqOUyAqH+uCjgD4nGQIQo+6IuralkwosssyxBzOpBl60m16NBsa8aSe+uXCru0swoiwWCoUt8w8wYkecOiq32rOJhwWRGph1mCI6kt8oh5khEYUYo-GO+FcdYAQ50hExh3hemSWIW86YWymaWJm-h3uuiYYqEGBgu2B4scIY+OgHa0InYTO8R5qiRFRRGDBO+mhmB2hjYjUL80wQQcwxgUQbeE6AWuGDBAw6+rRnq4wnQThE8YYHUcIM+luwo6xLBZ0jur+ToAcOgqkBOyilugiYxGx+2hhsBHUPgAYeg561m5WEMN4uEecQYp24scwF2kQQAA */ + createMachine( + { + id: "workspaceState", + predictableActionArguments: true, + tsTypes: {} as import("./workspaceXService.typegen").Typegen0, + schema: { + context: {} as WorkspaceContext, + events: {} as WorkspaceEvent, + services: {} as { + getWorkspace: { + data: TypesGen.Workspace + } + getTemplate: { + data: TypesGen.Template + } + startWorkspace: { + data: TypesGen.WorkspaceBuild + } + stopWorkspace: { + data: TypesGen.WorkspaceBuild + } + deleteWorkspace: { + data: TypesGen.WorkspaceBuild + } + cancelWorkspace: { + data: Types.Message + } + refreshWorkspace: { + data: TypesGen.Workspace | undefined + } + getResources: { + data: TypesGen.WorkspaceResource[] + } + getBuilds: { + data: TypesGen.WorkspaceBuild[] + } + loadMoreBuilds: { + data: TypesGen.WorkspaceBuild[] + } + checkPermissions: { + data: TypesGen.UserAuthorizationResponse + } }, - tags: "loading", }, - refreshingTemplate: { - entry: ["clearRefreshTemplateError"], - invoke: { - id: "refreshTemplate", - src: "getTemplate", - onDone: { - target: "gettingPermissions", - actions: ["assignTemplate"], - }, - onError: { - target: "error", - actions: ["assignRefreshTemplateError", "displayRefreshTemplateError"], - }, + initial: "idle", + on: { + GET_WORKSPACE: { + target: ".gettingWorkspace", + internal: false, }, - tags: "loading", }, - gettingPermissions: { - entry: "clearGetPermissionsError", - invoke: { - src: "checkPermissions", - id: "checkPermissions", - onDone: [ - { - actions: ["assignPermissions"], - target: "ready", - }, - ], - onError: [ - { - actions: "assignGetPermissionsError", - target: "error", - }, - ], + states: { + idle: { + tags: "loading", }, - }, - ready: { - type: "parallel", - states: { - // We poll the workspace consistently to know if it becomes outdated and to update build status - pollingWorkspace: { - initial: "refreshingWorkspace", - states: { - refreshingWorkspace: { - entry: "clearRefreshWorkspaceError", - invoke: { - id: "refreshWorkspace", - src: "refreshWorkspace", - onDone: { target: "waiting", actions: ["refreshTimeline", "assignWorkspace"] }, - onError: { target: "waiting", actions: "assignRefreshWorkspaceError" }, - }, + gettingWorkspace: { + entry: ["clearGetWorkspaceError", "clearContext"], + invoke: { + src: "getWorkspace", + id: "getWorkspace", + onDone: [ + { + actions: "assignWorkspace", + target: "refreshingTemplate", }, - waiting: { - after: { - 1000: "refreshingWorkspace", - }, + ], + onError: [ + { + actions: "assignGetWorkspaceError", + target: "error", }, - }, + ], }, - build: { - initial: "idle", - states: { - idle: { - on: { - START: "requestingStart", - STOP: "requestingStop", - ASK_DELETE: "askingDelete", - UPDATE: "refreshingTemplate", - CANCEL: "requestingCancel", - }, + tags: "loading", + }, + refreshingTemplate: { + entry: "clearRefreshTemplateError", + invoke: { + src: "getTemplate", + id: "refreshTemplate", + onDone: [ + { + actions: "assignTemplate", + target: "gettingPermissions", }, - askingDelete: { - on: { - DELETE: "requestingDelete", - CANCEL_DELETE: "idle", - }, + ], + onError: [ + { + actions: ["assignRefreshTemplateError", "displayRefreshTemplateError"], + target: "error", }, - requestingStart: { - entry: "clearBuildError", - invoke: { - id: "startWorkspace", - src: "startWorkspace", - onDone: { - target: "idle", - actions: ["assignBuild", "refreshTimeline"], + ], + }, + tags: "loading", + }, + gettingPermissions: { + entry: "clearGetPermissionsError", + invoke: { + src: "checkPermissions", + id: "checkPermissions", + onDone: [ + { + actions: "assignPermissions", + target: "ready", + }, + ], + onError: [ + { + actions: "assignGetPermissionsError", + target: "error", + }, + ], + }, + }, + ready: { + type: "parallel", + states: { + pollingWorkspace: { + initial: "refreshingWorkspace", + states: { + refreshingWorkspace: { + entry: "clearRefreshWorkspaceError", + invoke: { + src: "refreshWorkspace", + id: "refreshWorkspace", + onDone: [ + { + actions: ["refreshTimeline", "assignWorkspace"], + target: "waiting", + }, + ], + onError: [ + { + actions: "assignRefreshWorkspaceError", + target: "waiting", + }, + ], }, - onError: { - target: "idle", - actions: ["assignBuildError"], + }, + waiting: { + after: { + "1000": { + target: "refreshingWorkspace", + }, }, }, }, - requestingStop: { - entry: "clearBuildError", - invoke: { - id: "stopWorkspace", - src: "stopWorkspace", - onDone: { - target: "idle", - actions: ["assignBuild", "refreshTimeline"], - }, - onError: { - target: "idle", - actions: ["assignBuildError"], + }, + build: { + initial: "idle", + states: { + idle: { + on: { + START: { + target: "requestingStart", + }, + STOP: { + target: "requestingStop", + }, + ASK_DELETE: { + target: "askingDelete", + }, + UPDATE: { + target: "refreshingTemplate", + }, + CANCEL: { + target: "requestingCancel", + }, }, }, - }, - requestingDelete: { - entry: "clearBuildError", - invoke: { - id: "deleteWorkspace", - src: "deleteWorkspace", - onDone: { - target: "idle", - actions: ["assignBuild", "refreshTimeline"], + askingDelete: { + on: { + DELETE: { + target: "requestingDelete", + }, + CANCEL_DELETE: { + target: "idle", + }, }, - onError: { - target: "idle", - actions: ["assignBuildError"], + }, + requestingStart: { + entry: "clearBuildError", + invoke: { + src: "startWorkspace", + id: "startWorkspace", + onDone: [ + { + actions: ["assignBuild", "refreshTimeline"], + target: "idle", + }, + ], + onError: [ + { + actions: "assignBuildError", + target: "idle", + }, + ], }, }, - }, - requestingCancel: { - entry: ["clearCancellationMessage", "clearCancellationError"], - invoke: { - id: "cancelWorkspace", - src: "cancelWorkspace", - onDone: { - target: "idle", - actions: [ - "assignCancellationMessage", - "displayCancellationMessage", - "refreshTimeline", + requestingStop: { + entry: "clearBuildError", + invoke: { + src: "stopWorkspace", + id: "stopWorkspace", + onDone: [ + { + actions: ["assignBuild", "refreshTimeline"], + target: "idle", + }, + ], + onError: [ + { + actions: "assignBuildError", + target: "idle", + }, ], }, - onError: { - target: "idle", - actions: ["assignCancellationError"], + }, + requestingDelete: { + entry: "clearBuildError", + invoke: { + src: "deleteWorkspace", + id: "deleteWorkspace", + onDone: [ + { + actions: ["assignBuild", "refreshTimeline"], + target: "idle", + }, + ], + onError: [ + { + actions: "assignBuildError", + target: "idle", + }, + ], }, }, - }, - refreshingTemplate: { - entry: "clearRefreshTemplateError", - invoke: { - id: "refreshTemplate", - src: "getTemplate", - onDone: { - target: "requestingStart", - actions: "assignTemplate", + requestingCancel: { + entry: ["clearCancellationMessage", "clearCancellationError"], + invoke: { + src: "cancelWorkspace", + id: "cancelWorkspace", + onDone: [ + { + actions: [ + "assignCancellationMessage", + "displayCancellationMessage", + "refreshTimeline", + ], + target: "idle", + }, + ], + onError: [ + { + actions: "assignCancellationError", + target: "idle", + }, + ], }, - onError: { - target: "idle", - actions: ["assignRefreshTemplateError", "displayRefreshTemplateError"], + }, + refreshingTemplate: { + entry: "clearRefreshTemplateError", + invoke: { + src: "getTemplate", + id: "refreshTemplate", + onDone: [ + { + actions: "assignTemplate", + target: "requestingStart", + }, + ], + onError: [ + { + actions: ["assignRefreshTemplateError", "displayRefreshTemplateError"], + target: "idle", + }, + ], }, }, }, }, - }, - pollingResources: { - initial: "gettingResources", - states: { - gettingResources: { - entry: "clearGetResourcesError", - invoke: { - id: "getResources", - src: "getResources", - onDone: { target: "waiting", actions: "assignResources" }, - onError: { target: "waiting", actions: "assignGetResourcesError" }, + pollingResources: { + initial: "gettingResources", + states: { + gettingResources: { + entry: "clearGetResourcesError", + invoke: { + src: "getResources", + id: "getResources", + onDone: [ + { + actions: "assignResources", + target: "waiting", + }, + ], + onError: [ + { + actions: "assignGetResourcesError", + target: "waiting", + }, + ], + }, }, - }, - waiting: { - after: { - 5000: "gettingResources", + waiting: { + after: { + "5000": { + target: "gettingResources", + }, + }, }, }, }, - }, - - timeline: { - initial: "gettingBuilds", - states: { - idle: {}, - gettingBuilds: { - entry: "clearGetBuildsError", - invoke: { - src: "getBuilds", - onDone: { - actions: ["assignBuilds"], - target: "loadedBuilds", - }, - onError: { - actions: ["assignGetBuildsError"], - target: "idle", + timeline: { + initial: "gettingBuilds", + states: { + idle: {}, + gettingBuilds: { + entry: "clearGetBuildsError", + invoke: { + src: "getBuilds", + onDone: [ + { + actions: "assignBuilds", + target: "loadedBuilds", + }, + ], + onError: [ + { + actions: "assignGetBuildsError", + target: "idle", + }, + ], }, }, - }, - loadedBuilds: { - initial: "idle", - states: { - idle: { - on: { - LOAD_MORE_BUILDS: { - target: "loadingMoreBuilds", - cond: "hasMoreBuilds", + loadedBuilds: { + initial: "idle", + states: { + idle: { + on: { + LOAD_MORE_BUILDS: { + cond: "hasMoreBuilds", + target: "loadingMoreBuilds", + }, + REFRESH_TIMELINE: { + target: "#workspaceState.ready.timeline.gettingBuilds", + }, }, - REFRESH_TIMELINE: "#workspaceState.ready.timeline.gettingBuilds", }, - }, - loadingMoreBuilds: { - entry: "clearLoadMoreBuildsError", - invoke: { - src: "loadMoreBuilds", - onDone: { - actions: ["assignNewBuilds"], - target: "idle", - }, - onError: { - actions: ["assignLoadMoreBuildsError"], - target: "idle", + loadingMoreBuilds: { + entry: "clearLoadMoreBuildsError", + invoke: { + src: "loadMoreBuilds", + onDone: [ + { + actions: "assignNewBuilds", + target: "idle", + }, + ], + onError: [ + { + actions: "assignLoadMoreBuildsError", + target: "idle", + }, + ], }, }, }, @@ -372,231 +453,236 @@ export const workspaceMachine = createMachine( }, }, }, - }, - error: { - on: { - GET_WORKSPACE: "gettingWorkspace", + error: { + on: { + GET_WORKSPACE: { + target: "gettingWorkspace", + }, + }, }, }, }, - }, - { - actions: { - // Clear data about an old workspace when looking at a new one - clearContext: () => - assign({ - workspace: undefined, - template: undefined, - build: undefined, - permissions: undefined, + { + actions: { + // Clear data about an old workspace when looking at a new one + clearContext: () => + assign({ + workspace: undefined, + template: undefined, + build: undefined, + permissions: undefined, + }), + assignWorkspace: assign({ + workspace: (_, event) => event.data, }), - assignWorkspace: assign({ - workspace: (_, event) => event.data, - }), - assignGetWorkspaceError: assign({ - getWorkspaceError: (_, event) => event.data, - }), - clearGetWorkspaceError: (context) => assign({ ...context, getWorkspaceError: undefined }), - assignTemplate: assign({ - template: (_, event) => event.data, - }), - assignPermissions: assign({ - // Setting event.data as Permissions to be more stricted. So we know - // what permissions we asked for. - permissions: (_, event) => event.data as Permissions, - }), - assignGetPermissionsError: assign({ - checkPermissionsError: (_, event) => event.data, - }), - clearGetPermissionsError: assign({ - checkPermissionsError: (_) => undefined, - }), - assignBuild: assign({ - build: (_, event) => event.data, - }), - assignBuildError: assign({ - buildError: (_, event) => event.data, - }), - clearBuildError: assign({ - buildError: (_) => undefined, - }), - assignCancellationMessage: assign({ - cancellationMessage: (_, event) => event.data, - }), - clearCancellationMessage: assign({ - cancellationMessage: (_) => undefined, - }), - displayCancellationMessage: (context) => { - if (context.cancellationMessage) { - displaySuccess(context.cancellationMessage.message) - } - }, - assignCancellationError: assign({ - cancellationError: (_, event) => event.data, - }), - clearCancellationError: assign({ - cancellationError: (_) => undefined, - }), - assignRefreshWorkspaceError: assign({ - refreshWorkspaceError: (_, event) => event.data, - }), - clearRefreshWorkspaceError: assign({ - refreshWorkspaceError: (_) => undefined, - }), - assignRefreshTemplateError: assign({ - refreshTemplateError: (_, event) => event.data, - }), - displayRefreshTemplateError: () => { - displayError(Language.refreshTemplateError) - }, - clearRefreshTemplateError: assign({ - refreshTemplateError: (_) => undefined, - }), - // Resources - assignResources: assign({ - resources: (_, event) => event.data, - }), - assignGetResourcesError: assign({ - getResourcesError: (_, event) => event.data, - }), - clearGetResourcesError: assign({ - getResourcesError: (_) => undefined, - }), - // Timeline - assignBuilds: assign({ - builds: (_, event) => event.data, - }), - assignGetBuildsError: assign({ - getBuildsError: (_, event) => event.data, - }), - clearGetBuildsError: assign({ - getBuildsError: (_) => undefined, - }), - assignNewBuilds: assign({ - builds: (context, event) => { - const oldBuilds = context.builds - - if (!oldBuilds) { - // This state is theoretically impossible, but helps TS - throw new Error("workspaceXService: failed to load workspace builds") + assignGetWorkspaceError: assign({ + getWorkspaceError: (_, event) => event.data, + }), + clearGetWorkspaceError: (context) => assign({ ...context, getWorkspaceError: undefined }), + assignTemplate: assign({ + template: (_, event) => event.data, + }), + assignPermissions: assign({ + // Setting event.data as Permissions to be more stricted. So we know + // what permissions we asked for. + permissions: (_, event) => event.data as Permissions, + }), + assignGetPermissionsError: assign({ + checkPermissionsError: (_, event) => event.data, + }), + clearGetPermissionsError: assign({ + checkPermissionsError: (_) => undefined, + }), + assignBuild: assign({ + build: (_, event) => event.data, + }), + assignBuildError: assign({ + buildError: (_, event) => event.data, + }), + clearBuildError: assign({ + buildError: (_) => undefined, + }), + assignCancellationMessage: assign({ + cancellationMessage: (_, event) => event.data, + }), + clearCancellationMessage: assign({ + cancellationMessage: (_) => undefined, + }), + displayCancellationMessage: (context) => { + if (context.cancellationMessage) { + displaySuccess(context.cancellationMessage.message) } - - return [...oldBuilds, ...event.data] }, - }), - assignLoadMoreBuildsError: assign({ - loadMoreBuildsError: (_, event) => event.data, - }), - clearLoadMoreBuildsError: assign({ - loadMoreBuildsError: (_) => undefined, - }), - refreshTimeline: pure((context, event) => { - // No need to refresh the timeline if it is not loaded - if (!context.builds) { - return - } - // When it is a refresh workspace event, we want to check if the latest - // build was updated to not over fetch the builds - if (event.type === "done.invoke.refreshWorkspace") { - const latestBuildInTimeline = latestBuild(context.builds) - const isUpdated = event.data?.latest_build.updated_at !== latestBuildInTimeline.updated_at - if (isUpdated) { + assignCancellationError: assign({ + cancellationError: (_, event) => event.data, + }), + clearCancellationError: assign({ + cancellationError: (_) => undefined, + }), + assignRefreshWorkspaceError: assign({ + refreshWorkspaceError: (_, event) => event.data, + }), + clearRefreshWorkspaceError: assign({ + refreshWorkspaceError: (_) => undefined, + }), + assignRefreshTemplateError: assign({ + refreshTemplateError: (_, event) => event.data, + }), + displayRefreshTemplateError: () => { + displayError(Language.refreshTemplateError) + }, + clearRefreshTemplateError: assign({ + refreshTemplateError: (_) => undefined, + }), + // Resources + assignResources: assign({ + resources: (_, event) => event.data, + }), + assignGetResourcesError: assign({ + getResourcesError: (_, event) => event.data, + }), + clearGetResourcesError: assign({ + getResourcesError: (_) => undefined, + }), + // Timeline + assignBuilds: assign({ + builds: (_, event) => event.data, + }), + assignGetBuildsError: assign({ + getBuildsError: (_, event) => event.data, + }), + clearGetBuildsError: assign({ + getBuildsError: (_) => undefined, + }), + assignNewBuilds: assign({ + builds: (context, event) => { + const oldBuilds = context.builds + + if (!oldBuilds) { + // This state is theoretically impossible, but helps TS + throw new Error("workspaceXService: failed to load workspace builds") + } + + return [...oldBuilds, ...event.data] + }, + }), + assignLoadMoreBuildsError: assign({ + loadMoreBuildsError: (_, event) => event.data, + }), + clearLoadMoreBuildsError: assign({ + loadMoreBuildsError: (_) => undefined, + }), + refreshTimeline: pure((context, event) => { + // No need to refresh the timeline if it is not loaded + if (!context.builds) { + return + } + // When it is a refresh workspace event, we want to check if the latest + // build was updated to not over fetch the builds + if (event.type === "done.invoke.refreshWorkspace") { + const latestBuildInTimeline = latestBuild(context.builds) + const isUpdated = + event.data?.latest_build.updated_at !== latestBuildInTimeline.updated_at + if (isUpdated) { + return send({ type: "REFRESH_TIMELINE" }) + } + } else { return send({ type: "REFRESH_TIMELINE" }) } - } else { - return send({ type: "REFRESH_TIMELINE" }) - } - }), - }, - guards: { - hasMoreBuilds: (_) => false, - }, - services: { - getWorkspace: async (_, event) => { - return await API.getWorkspaceByOwnerAndName(event.username, event.workspaceName, { - include_deleted: true, - }) - }, - getTemplate: async (context) => { - if (context.workspace) { - return await API.getTemplate(context.workspace.template_id) - } else { - throw Error("Cannot get template without workspace") - } - }, - startWorkspace: async (context) => { - if (context.workspace) { - return await API.startWorkspace(context.workspace.id, context.template?.active_version_id) - } else { - throw Error("Cannot start workspace without workspace id") - } - }, - stopWorkspace: async (context) => { - if (context.workspace) { - return await API.stopWorkspace(context.workspace.id) - } else { - throw Error("Cannot stop workspace without workspace id") - } - }, - deleteWorkspace: async (context) => { - if (context.workspace) { - return await API.deleteWorkspace(context.workspace.id) - } else { - throw Error("Cannot delete workspace without workspace id") - } - }, - cancelWorkspace: async (context) => { - if (context.workspace) { - return await API.cancelWorkspaceBuild(context.workspace.latest_build.id) - } else { - throw Error("Cannot cancel workspace without build id") - } - }, - refreshWorkspace: async (context) => { - if (context.workspace) { - return await API.getWorkspaceByOwnerAndName( - context.workspace.owner_name, - context.workspace.name, - { - include_deleted: true, - }, - ) - } else { - throw Error("Cannot refresh workspace without id") - } - }, - getResources: async (context) => { - // If the job hasn't completed, fetching resources will result - // in an unfriendly error for the user. - if (!context.workspace?.latest_build.job.completed_at) { - return [] - } - const resources = await API.getWorkspaceResources(context.workspace.latest_build.id) - return resources - }, - getBuilds: async (context) => { - if (context.workspace) { - return await API.getWorkspaceBuilds(context.workspace.id) - } else { - throw Error("Cannot get builds without id") - } + }), }, - loadMoreBuilds: async (context) => { - if (context.workspace) { - return await API.getWorkspaceBuilds(context.workspace.id) - } else { - throw Error("Cannot load more builds without id") - } + guards: { + hasMoreBuilds: (_) => false, }, - checkPermissions: async (context) => { - if (context.workspace && context.userId) { - return await API.checkUserPermissions(context.userId, { - checks: permissionsToCheck(context.workspace), + services: { + getWorkspace: async (_, event) => { + return await API.getWorkspaceByOwnerAndName(event.username, event.workspaceName, { + include_deleted: true, }) - } else { - throw Error("Cannot check permissions without both workspace and user id") - } + }, + getTemplate: async (context) => { + if (context.workspace) { + return await API.getTemplate(context.workspace.template_id) + } else { + throw Error("Cannot get template without workspace") + } + }, + startWorkspace: async (context) => { + if (context.workspace) { + return await API.startWorkspace( + context.workspace.id, + context.template?.active_version_id, + ) + } else { + throw Error("Cannot start workspace without workspace id") + } + }, + stopWorkspace: async (context) => { + if (context.workspace) { + return await API.stopWorkspace(context.workspace.id) + } else { + throw Error("Cannot stop workspace without workspace id") + } + }, + deleteWorkspace: async (context) => { + if (context.workspace) { + return await API.deleteWorkspace(context.workspace.id) + } else { + throw Error("Cannot delete workspace without workspace id") + } + }, + cancelWorkspace: async (context) => { + if (context.workspace) { + return await API.cancelWorkspaceBuild(context.workspace.latest_build.id) + } else { + throw Error("Cannot cancel workspace without build id") + } + }, + refreshWorkspace: async (context) => { + if (context.workspace) { + return await API.getWorkspaceByOwnerAndName( + context.workspace.owner_name, + context.workspace.name, + { + include_deleted: true, + }, + ) + } else { + throw Error("Cannot refresh workspace without id") + } + }, + getResources: async (context) => { + // If the job hasn't completed, fetching resources will result + // in an unfriendly error for the user. + if (!context.workspace?.latest_build.job.completed_at) { + return [] + } + const resources = await API.getWorkspaceResources(context.workspace.latest_build.id) + return resources + }, + getBuilds: async (context) => { + if (context.workspace) { + return await API.getWorkspaceBuilds(context.workspace.id) + } else { + throw Error("Cannot get builds without id") + } + }, + loadMoreBuilds: async (context) => { + if (context.workspace) { + return await API.getWorkspaceBuilds(context.workspace.id) + } else { + throw Error("Cannot load more builds without id") + } + }, + checkPermissions: async (context) => { + if (context.workspace && context.userId) { + return await API.checkUserPermissions(context.userId, { + checks: permissionsToCheck(context.workspace), + }) + } else { + throw Error("Cannot check permissions without both workspace and user id") + } + }, }, }, - }, -) + ) diff --git a/site/src/xServices/workspaceBuild/workspaceBuildXService.ts b/site/src/xServices/workspaceBuild/workspaceBuildXService.ts index b49fa75a98e31..cbe080e0dbda7 100644 --- a/site/src/xServices/workspaceBuild/workspaceBuildXService.ts +++ b/site/src/xServices/workspaceBuild/workspaceBuildXService.ts @@ -24,6 +24,8 @@ type LogsEvent = { export const workspaceBuildMachine = createMachine( { id: "workspaceBuildState", + predictableActionArguments: true, + tsTypes: {} as import("./workspaceBuildXService.typegen").Typegen0, schema: { context: {} as LogsContext, events: {} as LogsEvent, @@ -36,7 +38,6 @@ export const workspaceBuildMachine = createMachine( } }, }, - tsTypes: {} as import("./workspaceBuildXService.typegen").Typegen0, initial: "gettingBuild", states: { gettingBuild: { diff --git a/site/src/xServices/workspaceSchedule/workspaceScheduleBannerXService.ts b/site/src/xServices/workspaceSchedule/workspaceScheduleBannerXService.ts index 007cd862c1835..5dd803bc3b9ae 100644 --- a/site/src/xServices/workspaceSchedule/workspaceScheduleBannerXService.ts +++ b/site/src/xServices/workspaceSchedule/workspaceScheduleBannerXService.ts @@ -21,11 +21,12 @@ export type WorkspaceScheduleBannerEvent = { export const workspaceScheduleBannerMachine = createMachine( { + id: "workspaceScheduleBannerState", + predictableActionArguments: true, tsTypes: {} as import("./workspaceScheduleBannerXService.typegen").Typegen0, schema: { events: {} as WorkspaceScheduleBannerEvent, }, - id: "workspaceScheduleBannerState", initial: "idle", states: { idle: { diff --git a/site/src/xServices/workspaceSchedule/workspaceScheduleXService.ts b/site/src/xServices/workspaceSchedule/workspaceScheduleXService.ts index 9fef3b34cd0f4..be45a8fdcb075 100644 --- a/site/src/xServices/workspaceSchedule/workspaceScheduleXService.ts +++ b/site/src/xServices/workspaceSchedule/workspaceScheduleXService.ts @@ -53,6 +53,8 @@ export type WorkspaceScheduleEvent = export const workspaceSchedule = createMachine( { + id: "workspaceScheduleState", + predictableActionArguments: true, tsTypes: {} as import("./workspaceScheduleXService.typegen").Typegen0, schema: { context: {} as WorkspaceScheduleContext, @@ -63,7 +65,6 @@ export const workspaceSchedule = createMachine( } }, }, - id: "workspaceScheduleState", initial: "idle", on: { GET_WORKSPACE: "gettingWorkspace", diff --git a/site/src/xServices/workspaces/workspacesXService.ts b/site/src/xServices/workspaces/workspacesXService.ts index 9bc3df854b711..026efec7ff1e4 100644 --- a/site/src/xServices/workspaces/workspacesXService.ts +++ b/site/src/xServices/workspaces/workspacesXService.ts @@ -28,6 +28,8 @@ type WorkspaceItemEvent = export const workspaceItemMachine = createMachine( { id: "workspaceItemMachine", + predictableActionArguments: true, + tsTypes: {} as import("./workspacesXService.typegen").Typegen0, schema: { context: {} as WorkspaceItemContext, events: {} as WorkspaceItemEvent, @@ -43,7 +45,6 @@ export const workspaceItemMachine = createMachine( } }, }, - tsTypes: {} as import("./workspacesXService.typegen").Typegen0, type: "parallel", states: { @@ -196,6 +197,7 @@ type WorkspacesEvent = export const workspacesMachine = createMachine( { + predictableActionArguments: true, tsTypes: {} as import("./workspacesXService.typegen").Typegen1, schema: { context: {} as WorkspacesContext, From 5a2088c819dabee7512e5068564a85c52dfb7bd3 Mon Sep 17 00:00:00 2001 From: Presley Pizzo Date: Mon, 12 Sep 2022 16:37:41 +0000 Subject: [PATCH 2/2] Remove layout strings --- .../xServices/templates/templatesXService.ts | 180 ++- .../xServices/workspace/workspaceXService.ts | 1092 ++++++++--------- 2 files changed, 632 insertions(+), 640 deletions(-) diff --git a/site/src/xServices/templates/templatesXService.ts b/site/src/xServices/templates/templatesXService.ts index 9b0d9484cf71b..8f59341550921 100644 --- a/site/src/xServices/templates/templatesXService.ts +++ b/site/src/xServices/templates/templatesXService.ts @@ -11,101 +11,99 @@ interface TemplatesContext { templatesError?: Error | unknown } -export const templatesMachine = - /** @xstate-layout N4IgpgJg5mDOIC5QBcwFsAOAbAhq2AysnmAHQzLICWAdlAPIBOUONVAXnlQPY2wDEEXmVoA3bgGsyFJizadqveEhAZusKopqJQAD0QAWAMwHSATgDsANgCsNgzeuOATABoQAT0QBGb89I2AAzB3oEAHH7eFtFhAL6x7qiYuPhEJORglLQMzKwcXEr8YIyM3Iyk2HgAZmVoGciyeQo8fDqq6potbfoIxqaWtvaOthZunogmRgHBgc4Wvs5mYbPxieiVqcSo9dR0ACrrKXCCwqRiktKZB8kkyqBqGlrdPsH9Zs6+VlZhxlbOBu4vAgzIFSDNgot5s4wnZViAkhs4GlthRdlBroiBMVSuUNjVGHUKBijnd2o8uioeqFAm8Pt4vj8jH8AeMEM5AjYwTMouEDGEzPTnPEEiAaNwIHA2giScjLlk6I15AVWioHp1eM9emMgb4zNMZh8wvMzH8LHDpbdZTtssTbm01U9KYgvqDmUsIt4+TYIoDECbzGZA2Y+lYjIEjIHzYdLVsyEIaGB7R1HXofOyLKQDIsrKELAYogKjL6EL4wlyZjCswYHBEozdNulsWUk+SNU6S+nM9nc-mLIXi845qQjCOjDZg3YwjC65jZS31dp294wsXl8LYkA */ - createMachine( - { - id: "templatesState", - predictableActionArguments: true, - tsTypes: {} as import("./templatesXService.typegen").Typegen0, - schema: { - context: {} as TemplatesContext, - services: {} as { - getOrganizations: { - data: TypesGen.Organization[] - } - getPermissions: { - data: boolean - } - getTemplates: { - data: TypesGen.Template[] - } - }, +export const templatesMachine = createMachine( + { + id: "templatesState", + predictableActionArguments: true, + tsTypes: {} as import("./templatesXService.typegen").Typegen0, + schema: { + context: {} as TemplatesContext, + services: {} as { + getOrganizations: { + data: TypesGen.Organization[] + } + getPermissions: { + data: boolean + } + getTemplates: { + data: TypesGen.Template[] + } }, - initial: "gettingOrganizations", - states: { - gettingOrganizations: { - entry: "clearOrganizationsError", - invoke: { - src: "getOrganizations", - id: "getOrganizations", - onDone: [ - { - actions: ["assignOrganizations", "clearOrganizationsError"], - target: "gettingTemplates", - }, - ], - onError: [ - { - actions: "assignOrganizationsError", - target: "error", - }, - ], - }, - tags: "loading", + }, + initial: "gettingOrganizations", + states: { + gettingOrganizations: { + entry: "clearOrganizationsError", + invoke: { + src: "getOrganizations", + id: "getOrganizations", + onDone: [ + { + actions: ["assignOrganizations", "clearOrganizationsError"], + target: "gettingTemplates", + }, + ], + onError: [ + { + actions: "assignOrganizationsError", + target: "error", + }, + ], }, - gettingTemplates: { - entry: "clearTemplatesError", - invoke: { - src: "getTemplates", - id: "getTemplates", - onDone: [ - { - actions: ["assignTemplates", "clearTemplatesError"], - target: "done", - }, - ], - onError: [ - { - actions: "assignTemplatesError", - target: "error", - }, - ], - }, - tags: "loading", + tags: "loading", + }, + gettingTemplates: { + entry: "clearTemplatesError", + invoke: { + src: "getTemplates", + id: "getTemplates", + onDone: [ + { + actions: ["assignTemplates", "clearTemplatesError"], + target: "done", + }, + ], + onError: [ + { + actions: "assignTemplatesError", + target: "error", + }, + ], }, - done: {}, - error: {}, + tags: "loading", }, + done: {}, + error: {}, }, - { - actions: { - assignOrganizations: assign({ - organizations: (_, event) => event.data, - }), - assignOrganizationsError: assign({ - organizationsError: (_, event) => event.data, - }), - clearOrganizationsError: assign((context) => ({ - ...context, - organizationsError: undefined, - })), - assignTemplates: assign({ - templates: (_, event) => event.data, - }), - assignTemplatesError: assign({ - templatesError: (_, event) => event.data, - }), - clearTemplatesError: (context) => assign({ ...context, getWorkspacesError: undefined }), - }, - services: { - getOrganizations: API.getOrganizations, - getTemplates: async (context) => { - if (!context.organizations || context.organizations.length === 0) { - throw new Error("no organizations") - } - return API.getTemplates(context.organizations[0].id) - }, + }, + { + actions: { + assignOrganizations: assign({ + organizations: (_, event) => event.data, + }), + assignOrganizationsError: assign({ + organizationsError: (_, event) => event.data, + }), + clearOrganizationsError: assign((context) => ({ + ...context, + organizationsError: undefined, + })), + assignTemplates: assign({ + templates: (_, event) => event.data, + }), + assignTemplatesError: assign({ + templatesError: (_, event) => event.data, + }), + clearTemplatesError: (context) => assign({ ...context, getWorkspacesError: undefined }), + }, + services: { + getOrganizations: API.getOrganizations, + getTemplates: async (context) => { + if (!context.organizations || context.organizations.length === 0) { + throw new Error("no organizations") + } + return API.getTemplates(context.organizations[0].id) }, }, - ) + }, +) diff --git a/site/src/xServices/workspace/workspaceXService.ts b/site/src/xServices/workspace/workspaceXService.ts index 88ac29ff029a0..08f5261147964 100644 --- a/site/src/xServices/workspace/workspaceXService.ts +++ b/site/src/xServices/workspace/workspaceXService.ts @@ -79,373 +79,370 @@ const permissionsToCheck = (workspace: TypesGen.Workspace) => ({ }, }) -export const workspaceMachine = - /** @xstate-layout N4IgpgJg5mDOIC5QHcD2AnA1rADgQwGMwBlAFz1LADoZTSBLAOygHUNt8iBiCVR6pgDdUmarTZZchMIlA5Usegz6yQAD0QAWAAwAmKgHYAbAFYjADgDMB80YCcu87oA0IAJ6JLARhP6Dly01dO1tzAztTAF9I1zRJThJyShowOiZWdiluMHR0DCocABsKADMMAFsU0gkOaVV5RWVGVQ0EOwMvQxNw7VsHbU1Nc1cPBEtgy0MAoIcTE20vI0to2MyEsgpqdDAS7dgAC3SAFTByos2ePgFGYVEqbd24fZOz4sp6hSV6FSR1LT1DKYLNY+o4XO5EI4DH5prpfHYAgYViA4rUiBtkg89odmC9zpQuDk8ugCm8yuhKlinni3jJfg0vj9QK0dH4gVYbPYwSNPNprFNAroDNptAYOl4kTEUWtpBixKkGMwAAo5cr0WCKPiwS78KhCETUAj7MAETAqinqzWMeD0z5NFqILx6fQWAwmOzzfzmII8hCLTSTIxB8USyxGLzLKWorKJTZVRVQc1qjXfa2E3L5fHkypGk1m1WW1M2uR21MOv3Oqiu92eyze8GjRx2OxUXSw0yaIxw8zI6PrJJbMB4CBuAqoQqFdI1GP3HbYqcy7i8XX6u5Ug7ThIfRpl36tUOTbQI8wDMxeHxGX0dcxUEUirwRJ29Nu9xexzFDkdjicL+LSWePAcv5omA6bEqSpQVAB2KbnUto7kyfx+v4h7Hqe4YXr6Sz6Heei9NYRhBJor5-uiA6zsOo7yD+zCwUQVDIHgXzMFwaiwOReAlJQ6AABRPtoACUXB9rK5HbJR36TrRb4MUxCbboyzR7o65gmJorZ8hKHQdJY2hzL6Jjered4RuYXi2JoEYkSBcoUV+ABGACu9CFBAeoQIUoHEEcACCABKRwKfaykILoR7aLeXZzIE4yqZoBi+hGenGSKgzaEGdh6SY1kxrZ4kOc5rnuZ5XDeQA8kqQW7sykLhZFcImDFjhqQlEKhboXj6AEgTpeeekSsRUZvnln6jk5LlufQHmgT5xAANIAPoACIAKIADIrUcK1VYhrRhZl9XRQGzXxYlAwGClAznuK3p2Dl-ZxvlY2FZN01cAAqkqS0+VtO1KTVoV1elDVNXFrWjANRiXUGFhmeG92iY9o1UONRVTSVADCPkAHIY+tf3lvtEXA0dsUtYlhmHneZgniebqDaspHvoOEmo25eCwJg6RLWAnkEqtG2-fBimE7ouhQ2YcJ2BK5hme0l5tR6nS4UKEbeE4d1DUzI2sy9VAc1zzA83zoFY7j63Letm3bcLwUAx1RgRR1R4RHYllOhKvrNi2uGBD4HXegjZFI7rE2zgAjo5cAJhs6CkDq1y3NQ7F4HHdF0iWCH-UhQomJ04bQnpEwB4lqk3t1Oi6Z2miekHzN2c9YfbJH0fpLH8dEpmZJQSnadvgTIW5+pEqu7Y8wim7iVePFVDjwMst8hERh1zrBVN2ALfsW3pCoDgCd6jcBpUOxu-pwP9udfoedmEYxidYRnttftF0V3yuiaG74zL1rNlicjbMRyjlvZgZBd5gS7pBCkx8d44DPrbaqOdOomFvDYRYR57DHXBrVc8VBX6DGMM2SMjNf4hzXkVZuQCEzG1SKBZcicj4QF5jQuBmcRYhQlGLKsZMlhBCDJ2CmhlcHdQRDYBYNciHSm1n-UO5CN6UO5kwgkncSRZigowk2LCQAMjtkhDhLpuGCj4QrCG8UurCPHmKPSEiRLBw-DItyFDW7MAxngRgRBCj71XIaVx7jNHaIQXtOqVhHaWBvtfMwiUAw+zvB-MugQlgr2kWQhxcinFQBcW43m4CVHdygQQHxvM-Gll2pCJ0N53R1mnldEIdhEqhKpiKPOvR3TpWyj-XKSTG6yMAjiKANILh0IPknaC1JTj4gzlo4p2c9oGBnt4OEEpF6NXaIlYUyDX5hm0sYRJpCukpJ6ccMZtJskQVINmEZBx+nvHgSUwGB0SaNWOmDRKSxlZ3iWE4YUxhJTEI6bsyS6Q-JwFQI5dARBYDxkBcC0F4LPGHzuLQIFsAQVgrgOfXRFhOjvzbD4XopjjC+jrMTEyfJvTmUajsuxX5qJSSgEilF4LIXMHpTCuAJzVFQMRdC1FxZJlZ3LIsMyrYgjeHmN6aEBKn5u0uueDCsy1IM0kSQqlVFxy0pZTy2SzEoCsRTskTi3EeJzyEjY+uT0AXMu5Yyxi2r0X7jFFi8y5gIgBFUosSwvp35Q1wqeBwsyAxtN+Q9FVVAGDlF5kweUaRmAACEXrakGV4hiw1OmhvoOGqSUaExxomrABA+p8lNAANraAALp2sdLFW8x4P7iLmA2SElgERUCsH7PQbsF4-KVX8kNYaI26loNm+N7LcmVFNavUcfbM1MqgDm1yeaC0UFTCW8tNzpmVscNWustbGr1sJRGKGFcxaVNsLoSlLMvxTsjVQQoqBhyQDnRACF6NQJrTKj5JaC0ACyZU-IrQWjG96ABJNaS1iAVuQr0Ks15vmEVmV4T1jsWwV2njFWV38g2I17em-t1Bb33ogI+59b0-0ADE-3EAABILSOEBr960gPYxtqwnRgTGpUAlOZJtstOqy09f6ltsJRQRmFGe9pwaL2Tpw9O-DjDCPxpvXeiA6Qv0YDAERuFwzx2pqvbqWTD6FOyZU2poj+bD6FuXWWiDiwPQcfCB0AYEQ5iGU9SeZDsIwxHiCGJzDtjJNpozde-T8nc2KeHMZ7YGnlGnPOdp-5um8NKYM6FozzBVORfjWZ4QFm+Arus-YZBI8HMf1MHMYYT9oSTCPUMMMIQfPdok1QZRXAADim0FosF-XNYgSofJ4wg+0ToboeiggGEMQl79kEoW822R2PhA0Naw6BNrRwOtdZ6315jfK2EAx9G1AITpWywjzt4fw3RohSkYKgRhvK4vJBfRBvbowAgWCO01XF-gu13azcBGMEHwxO00mEMMnUwwmAmz4WewZb5+sIhS8TS2Lm9KuRM-xtynu8nfgKAMnGWkInPTOpMhYtT-c4dWQicsTzg6flYCK039oM4w4tvzDcLUZCZkj37W410CvVlu26dbfBYQ-rPO8wQP7dk7AT81NKuf-htfJHn7CQgXRsJlR8YpVLGMQBTy678RFWBfAjlnMu1Vy6INZ8X-Od2hKF21POOETJ1kakKaE0v-56we0rgGD485Q7hKyewftqcQ26BdOecwPnYvd-Y-WnMFEmwg22OZSDwwIgfPUs6ukugigIuGCwNcY-JMAWk9uSeVdHaiXTd+7rS4iiET1MWrT2g9mN2aj369N4xxgUnwIL9U8Z4z41T1SVBM9VmdLXw78i97JL8AqA1DrksYCZW8y1u3a7rtyYptY+m3BAn44axKb-kAMcfPjJ7je8p7hGn7wCJh9tWnmYUXIoljzF8KpL7x+Q2n7nE8Q5rwmwvejsuCmUt8syz85kLyboDeOg7qzqzYM+KML0lu0qR426G+tuDaCAYQ0S94Yo8q08revm7eEksulqyKrKEKg6UKlBPK1mfO6BAum+2Boql0ooD86utgSB5BdKVqcAWqiuy+tyD4UGRW0sCIuchE+6xK7y6sryR+Ui-yvBGq4KqB6kTBNue6j+syl0sUoowQ4sSBCWxUqOUyAqH+uCjgD4nGQIQo+6IuralkwosssyxBzOpBl60m16NBsa8aSe+uXCru0swoiwWCoUt8w8wYkecOiq32rOJhwWRGph1mCI6kt8oh5khEYUYo-GO+FcdYAQ50hExh3hemSWIW86YWymaWJm-h3uuiYYqEGBgu2B4scIY+OgHa0InYTO8R5qiRFRRGDBO+mhmB2hjYjUL80wQQcwxgUQbeE6AWuGDBAw6+rRnq4wnQThE8YYHUcIM+luwo6xLBZ0jur+ToAcOgqkBOyilugiYxGx+2hhsBHUPgAYeg561m5WEMN4uEecQYp24scwF2kQQAA */ - createMachine( - { - id: "workspaceState", - predictableActionArguments: true, - tsTypes: {} as import("./workspaceXService.typegen").Typegen0, - schema: { - context: {} as WorkspaceContext, - events: {} as WorkspaceEvent, - services: {} as { - getWorkspace: { - data: TypesGen.Workspace - } - getTemplate: { - data: TypesGen.Template - } - startWorkspace: { - data: TypesGen.WorkspaceBuild - } - stopWorkspace: { - data: TypesGen.WorkspaceBuild - } - deleteWorkspace: { - data: TypesGen.WorkspaceBuild - } - cancelWorkspace: { - data: Types.Message - } - refreshWorkspace: { - data: TypesGen.Workspace | undefined - } - getResources: { - data: TypesGen.WorkspaceResource[] - } - getBuilds: { - data: TypesGen.WorkspaceBuild[] - } - loadMoreBuilds: { - data: TypesGen.WorkspaceBuild[] - } - checkPermissions: { - data: TypesGen.UserAuthorizationResponse - } - }, +export const workspaceMachine = createMachine( + { + id: "workspaceState", + predictableActionArguments: true, + tsTypes: {} as import("./workspaceXService.typegen").Typegen0, + schema: { + context: {} as WorkspaceContext, + events: {} as WorkspaceEvent, + services: {} as { + getWorkspace: { + data: TypesGen.Workspace + } + getTemplate: { + data: TypesGen.Template + } + startWorkspace: { + data: TypesGen.WorkspaceBuild + } + stopWorkspace: { + data: TypesGen.WorkspaceBuild + } + deleteWorkspace: { + data: TypesGen.WorkspaceBuild + } + cancelWorkspace: { + data: Types.Message + } + refreshWorkspace: { + data: TypesGen.Workspace | undefined + } + getResources: { + data: TypesGen.WorkspaceResource[] + } + getBuilds: { + data: TypesGen.WorkspaceBuild[] + } + loadMoreBuilds: { + data: TypesGen.WorkspaceBuild[] + } + checkPermissions: { + data: TypesGen.UserAuthorizationResponse + } }, - initial: "idle", - on: { - GET_WORKSPACE: { - target: ".gettingWorkspace", - internal: false, - }, + }, + initial: "idle", + on: { + GET_WORKSPACE: { + target: ".gettingWorkspace", + internal: false, + }, + }, + states: { + idle: { + tags: "loading", }, - states: { - idle: { - tags: "loading", + gettingWorkspace: { + entry: ["clearGetWorkspaceError", "clearContext"], + invoke: { + src: "getWorkspace", + id: "getWorkspace", + onDone: [ + { + actions: "assignWorkspace", + target: "refreshingTemplate", + }, + ], + onError: [ + { + actions: "assignGetWorkspaceError", + target: "error", + }, + ], }, - gettingWorkspace: { - entry: ["clearGetWorkspaceError", "clearContext"], - invoke: { - src: "getWorkspace", - id: "getWorkspace", - onDone: [ - { - actions: "assignWorkspace", - target: "refreshingTemplate", - }, - ], - onError: [ - { - actions: "assignGetWorkspaceError", - target: "error", - }, - ], - }, - tags: "loading", + tags: "loading", + }, + refreshingTemplate: { + entry: "clearRefreshTemplateError", + invoke: { + src: "getTemplate", + id: "refreshTemplate", + onDone: [ + { + actions: "assignTemplate", + target: "gettingPermissions", + }, + ], + onError: [ + { + actions: ["assignRefreshTemplateError", "displayRefreshTemplateError"], + target: "error", + }, + ], }, - refreshingTemplate: { - entry: "clearRefreshTemplateError", - invoke: { - src: "getTemplate", - id: "refreshTemplate", - onDone: [ - { - actions: "assignTemplate", - target: "gettingPermissions", - }, - ], - onError: [ - { - actions: ["assignRefreshTemplateError", "displayRefreshTemplateError"], - target: "error", - }, - ], - }, - tags: "loading", + tags: "loading", + }, + gettingPermissions: { + entry: "clearGetPermissionsError", + invoke: { + src: "checkPermissions", + id: "checkPermissions", + onDone: [ + { + actions: "assignPermissions", + target: "ready", + }, + ], + onError: [ + { + actions: "assignGetPermissionsError", + target: "error", + }, + ], }, - gettingPermissions: { - entry: "clearGetPermissionsError", - invoke: { - src: "checkPermissions", - id: "checkPermissions", - onDone: [ - { - actions: "assignPermissions", - target: "ready", + }, + ready: { + type: "parallel", + states: { + pollingWorkspace: { + initial: "refreshingWorkspace", + states: { + refreshingWorkspace: { + entry: "clearRefreshWorkspaceError", + invoke: { + src: "refreshWorkspace", + id: "refreshWorkspace", + onDone: [ + { + actions: ["refreshTimeline", "assignWorkspace"], + target: "waiting", + }, + ], + onError: [ + { + actions: "assignRefreshWorkspaceError", + target: "waiting", + }, + ], + }, }, - ], - onError: [ - { - actions: "assignGetPermissionsError", - target: "error", + waiting: { + after: { + "1000": { + target: "refreshingWorkspace", + }, + }, }, - ], + }, }, - }, - ready: { - type: "parallel", - states: { - pollingWorkspace: { - initial: "refreshingWorkspace", - states: { - refreshingWorkspace: { - entry: "clearRefreshWorkspaceError", - invoke: { - src: "refreshWorkspace", - id: "refreshWorkspace", - onDone: [ - { - actions: ["refreshTimeline", "assignWorkspace"], - target: "waiting", - }, - ], - onError: [ - { - actions: "assignRefreshWorkspaceError", - target: "waiting", - }, - ], + build: { + initial: "idle", + states: { + idle: { + on: { + START: { + target: "requestingStart", + }, + STOP: { + target: "requestingStop", + }, + ASK_DELETE: { + target: "askingDelete", + }, + UPDATE: { + target: "refreshingTemplate", + }, + CANCEL: { + target: "requestingCancel", }, }, - waiting: { - after: { - "1000": { - target: "refreshingWorkspace", - }, + }, + askingDelete: { + on: { + DELETE: { + target: "requestingDelete", + }, + CANCEL_DELETE: { + target: "idle", }, }, }, - }, - build: { - initial: "idle", - states: { - idle: { - on: { - START: { - target: "requestingStart", - }, - STOP: { - target: "requestingStop", + requestingStart: { + entry: "clearBuildError", + invoke: { + src: "startWorkspace", + id: "startWorkspace", + onDone: [ + { + actions: ["assignBuild", "refreshTimeline"], + target: "idle", }, - ASK_DELETE: { - target: "askingDelete", + ], + onError: [ + { + actions: "assignBuildError", + target: "idle", }, - UPDATE: { - target: "refreshingTemplate", + ], + }, + }, + requestingStop: { + entry: "clearBuildError", + invoke: { + src: "stopWorkspace", + id: "stopWorkspace", + onDone: [ + { + actions: ["assignBuild", "refreshTimeline"], + target: "idle", }, - CANCEL: { - target: "requestingCancel", + ], + onError: [ + { + actions: "assignBuildError", + target: "idle", }, - }, + ], }, - askingDelete: { - on: { - DELETE: { - target: "requestingDelete", + }, + requestingDelete: { + entry: "clearBuildError", + invoke: { + src: "deleteWorkspace", + id: "deleteWorkspace", + onDone: [ + { + actions: ["assignBuild", "refreshTimeline"], + target: "idle", }, - CANCEL_DELETE: { + ], + onError: [ + { + actions: "assignBuildError", target: "idle", }, - }, + ], }, - requestingStart: { - entry: "clearBuildError", - invoke: { - src: "startWorkspace", - id: "startWorkspace", - onDone: [ - { - actions: ["assignBuild", "refreshTimeline"], - target: "idle", - }, - ], - onError: [ - { - actions: "assignBuildError", - target: "idle", - }, - ], - }, - }, - requestingStop: { - entry: "clearBuildError", - invoke: { - src: "stopWorkspace", - id: "stopWorkspace", - onDone: [ - { - actions: ["assignBuild", "refreshTimeline"], - target: "idle", - }, - ], - onError: [ - { - actions: "assignBuildError", - target: "idle", - }, - ], - }, + }, + requestingCancel: { + entry: ["clearCancellationMessage", "clearCancellationError"], + invoke: { + src: "cancelWorkspace", + id: "cancelWorkspace", + onDone: [ + { + actions: [ + "assignCancellationMessage", + "displayCancellationMessage", + "refreshTimeline", + ], + target: "idle", + }, + ], + onError: [ + { + actions: "assignCancellationError", + target: "idle", + }, + ], }, - requestingDelete: { - entry: "clearBuildError", - invoke: { - src: "deleteWorkspace", - id: "deleteWorkspace", - onDone: [ - { - actions: ["assignBuild", "refreshTimeline"], - target: "idle", - }, - ], - onError: [ - { - actions: "assignBuildError", - target: "idle", - }, - ], - }, + }, + refreshingTemplate: { + entry: "clearRefreshTemplateError", + invoke: { + src: "getTemplate", + id: "refreshTemplate", + onDone: [ + { + actions: "assignTemplate", + target: "requestingStart", + }, + ], + onError: [ + { + actions: ["assignRefreshTemplateError", "displayRefreshTemplateError"], + target: "idle", + }, + ], }, - requestingCancel: { - entry: ["clearCancellationMessage", "clearCancellationError"], - invoke: { - src: "cancelWorkspace", - id: "cancelWorkspace", - onDone: [ - { - actions: [ - "assignCancellationMessage", - "displayCancellationMessage", - "refreshTimeline", - ], - target: "idle", - }, - ], - onError: [ - { - actions: "assignCancellationError", - target: "idle", - }, - ], - }, + }, + }, + }, + pollingResources: { + initial: "gettingResources", + states: { + gettingResources: { + entry: "clearGetResourcesError", + invoke: { + src: "getResources", + id: "getResources", + onDone: [ + { + actions: "assignResources", + target: "waiting", + }, + ], + onError: [ + { + actions: "assignGetResourcesError", + target: "waiting", + }, + ], }, - refreshingTemplate: { - entry: "clearRefreshTemplateError", - invoke: { - src: "getTemplate", - id: "refreshTemplate", - onDone: [ - { - actions: "assignTemplate", - target: "requestingStart", - }, - ], - onError: [ - { - actions: ["assignRefreshTemplateError", "displayRefreshTemplateError"], - target: "idle", - }, - ], + }, + waiting: { + after: { + "5000": { + target: "gettingResources", }, }, }, }, - pollingResources: { - initial: "gettingResources", - states: { - gettingResources: { - entry: "clearGetResourcesError", - invoke: { - src: "getResources", - id: "getResources", - onDone: [ - { - actions: "assignResources", - target: "waiting", - }, - ], - onError: [ - { - actions: "assignGetResourcesError", - target: "waiting", - }, - ], - }, - }, - waiting: { - after: { - "5000": { - target: "gettingResources", + }, + timeline: { + initial: "gettingBuilds", + states: { + idle: {}, + gettingBuilds: { + entry: "clearGetBuildsError", + invoke: { + src: "getBuilds", + onDone: [ + { + actions: "assignBuilds", + target: "loadedBuilds", }, - }, + ], + onError: [ + { + actions: "assignGetBuildsError", + target: "idle", + }, + ], }, }, - }, - timeline: { - initial: "gettingBuilds", - states: { - idle: {}, - gettingBuilds: { - entry: "clearGetBuildsError", - invoke: { - src: "getBuilds", - onDone: [ - { - actions: "assignBuilds", - target: "loadedBuilds", + loadedBuilds: { + initial: "idle", + states: { + idle: { + on: { + LOAD_MORE_BUILDS: { + cond: "hasMoreBuilds", + target: "loadingMoreBuilds", }, - ], - onError: [ - { - actions: "assignGetBuildsError", - target: "idle", + REFRESH_TIMELINE: { + target: "#workspaceState.ready.timeline.gettingBuilds", }, - ], + }, }, - }, - loadedBuilds: { - initial: "idle", - states: { - idle: { - on: { - LOAD_MORE_BUILDS: { - cond: "hasMoreBuilds", - target: "loadingMoreBuilds", + loadingMoreBuilds: { + entry: "clearLoadMoreBuildsError", + invoke: { + src: "loadMoreBuilds", + onDone: [ + { + actions: "assignNewBuilds", + target: "idle", }, - REFRESH_TIMELINE: { - target: "#workspaceState.ready.timeline.gettingBuilds", + ], + onError: [ + { + actions: "assignLoadMoreBuildsError", + target: "idle", }, - }, - }, - loadingMoreBuilds: { - entry: "clearLoadMoreBuildsError", - invoke: { - src: "loadMoreBuilds", - onDone: [ - { - actions: "assignNewBuilds", - target: "idle", - }, - ], - onError: [ - { - actions: "assignLoadMoreBuildsError", - target: "idle", - }, - ], - }, + ], }, }, }, @@ -453,236 +450,233 @@ export const workspaceMachine = }, }, }, - error: { - on: { - GET_WORKSPACE: { - target: "gettingWorkspace", - }, + }, + error: { + on: { + GET_WORKSPACE: { + target: "gettingWorkspace", }, }, }, }, - { - actions: { - // Clear data about an old workspace when looking at a new one - clearContext: () => - assign({ - workspace: undefined, - template: undefined, - build: undefined, - permissions: undefined, - }), - assignWorkspace: assign({ - workspace: (_, event) => event.data, - }), - assignGetWorkspaceError: assign({ - getWorkspaceError: (_, event) => event.data, - }), - clearGetWorkspaceError: (context) => assign({ ...context, getWorkspaceError: undefined }), - assignTemplate: assign({ - template: (_, event) => event.data, - }), - assignPermissions: assign({ - // Setting event.data as Permissions to be more stricted. So we know - // what permissions we asked for. - permissions: (_, event) => event.data as Permissions, - }), - assignGetPermissionsError: assign({ - checkPermissionsError: (_, event) => event.data, - }), - clearGetPermissionsError: assign({ - checkPermissionsError: (_) => undefined, - }), - assignBuild: assign({ - build: (_, event) => event.data, - }), - assignBuildError: assign({ - buildError: (_, event) => event.data, - }), - clearBuildError: assign({ - buildError: (_) => undefined, - }), - assignCancellationMessage: assign({ - cancellationMessage: (_, event) => event.data, - }), - clearCancellationMessage: assign({ - cancellationMessage: (_) => undefined, - }), - displayCancellationMessage: (context) => { - if (context.cancellationMessage) { - displaySuccess(context.cancellationMessage.message) - } - }, - assignCancellationError: assign({ - cancellationError: (_, event) => event.data, - }), - clearCancellationError: assign({ - cancellationError: (_) => undefined, - }), - assignRefreshWorkspaceError: assign({ - refreshWorkspaceError: (_, event) => event.data, - }), - clearRefreshWorkspaceError: assign({ - refreshWorkspaceError: (_) => undefined, - }), - assignRefreshTemplateError: assign({ - refreshTemplateError: (_, event) => event.data, - }), - displayRefreshTemplateError: () => { - displayError(Language.refreshTemplateError) - }, - clearRefreshTemplateError: assign({ - refreshTemplateError: (_) => undefined, - }), - // Resources - assignResources: assign({ - resources: (_, event) => event.data, - }), - assignGetResourcesError: assign({ - getResourcesError: (_, event) => event.data, - }), - clearGetResourcesError: assign({ - getResourcesError: (_) => undefined, - }), - // Timeline - assignBuilds: assign({ - builds: (_, event) => event.data, - }), - assignGetBuildsError: assign({ - getBuildsError: (_, event) => event.data, - }), - clearGetBuildsError: assign({ - getBuildsError: (_) => undefined, + }, + { + actions: { + // Clear data about an old workspace when looking at a new one + clearContext: () => + assign({ + workspace: undefined, + template: undefined, + build: undefined, + permissions: undefined, }), - assignNewBuilds: assign({ - builds: (context, event) => { - const oldBuilds = context.builds - - if (!oldBuilds) { - // This state is theoretically impossible, but helps TS - throw new Error("workspaceXService: failed to load workspace builds") - } + assignWorkspace: assign({ + workspace: (_, event) => event.data, + }), + assignGetWorkspaceError: assign({ + getWorkspaceError: (_, event) => event.data, + }), + clearGetWorkspaceError: (context) => assign({ ...context, getWorkspaceError: undefined }), + assignTemplate: assign({ + template: (_, event) => event.data, + }), + assignPermissions: assign({ + // Setting event.data as Permissions to be more stricted. So we know + // what permissions we asked for. + permissions: (_, event) => event.data as Permissions, + }), + assignGetPermissionsError: assign({ + checkPermissionsError: (_, event) => event.data, + }), + clearGetPermissionsError: assign({ + checkPermissionsError: (_) => undefined, + }), + assignBuild: assign({ + build: (_, event) => event.data, + }), + assignBuildError: assign({ + buildError: (_, event) => event.data, + }), + clearBuildError: assign({ + buildError: (_) => undefined, + }), + assignCancellationMessage: assign({ + cancellationMessage: (_, event) => event.data, + }), + clearCancellationMessage: assign({ + cancellationMessage: (_) => undefined, + }), + displayCancellationMessage: (context) => { + if (context.cancellationMessage) { + displaySuccess(context.cancellationMessage.message) + } + }, + assignCancellationError: assign({ + cancellationError: (_, event) => event.data, + }), + clearCancellationError: assign({ + cancellationError: (_) => undefined, + }), + assignRefreshWorkspaceError: assign({ + refreshWorkspaceError: (_, event) => event.data, + }), + clearRefreshWorkspaceError: assign({ + refreshWorkspaceError: (_) => undefined, + }), + assignRefreshTemplateError: assign({ + refreshTemplateError: (_, event) => event.data, + }), + displayRefreshTemplateError: () => { + displayError(Language.refreshTemplateError) + }, + clearRefreshTemplateError: assign({ + refreshTemplateError: (_) => undefined, + }), + // Resources + assignResources: assign({ + resources: (_, event) => event.data, + }), + assignGetResourcesError: assign({ + getResourcesError: (_, event) => event.data, + }), + clearGetResourcesError: assign({ + getResourcesError: (_) => undefined, + }), + // Timeline + assignBuilds: assign({ + builds: (_, event) => event.data, + }), + assignGetBuildsError: assign({ + getBuildsError: (_, event) => event.data, + }), + clearGetBuildsError: assign({ + getBuildsError: (_) => undefined, + }), + assignNewBuilds: assign({ + builds: (context, event) => { + const oldBuilds = context.builds - return [...oldBuilds, ...event.data] - }, - }), - assignLoadMoreBuildsError: assign({ - loadMoreBuildsError: (_, event) => event.data, - }), - clearLoadMoreBuildsError: assign({ - loadMoreBuildsError: (_) => undefined, - }), - refreshTimeline: pure((context, event) => { - // No need to refresh the timeline if it is not loaded - if (!context.builds) { - return + if (!oldBuilds) { + // This state is theoretically impossible, but helps TS + throw new Error("workspaceXService: failed to load workspace builds") } - // When it is a refresh workspace event, we want to check if the latest - // build was updated to not over fetch the builds - if (event.type === "done.invoke.refreshWorkspace") { - const latestBuildInTimeline = latestBuild(context.builds) - const isUpdated = - event.data?.latest_build.updated_at !== latestBuildInTimeline.updated_at - if (isUpdated) { - return send({ type: "REFRESH_TIMELINE" }) - } - } else { + + return [...oldBuilds, ...event.data] + }, + }), + assignLoadMoreBuildsError: assign({ + loadMoreBuildsError: (_, event) => event.data, + }), + clearLoadMoreBuildsError: assign({ + loadMoreBuildsError: (_) => undefined, + }), + refreshTimeline: pure((context, event) => { + // No need to refresh the timeline if it is not loaded + if (!context.builds) { + return + } + // When it is a refresh workspace event, we want to check if the latest + // build was updated to not over fetch the builds + if (event.type === "done.invoke.refreshWorkspace") { + const latestBuildInTimeline = latestBuild(context.builds) + const isUpdated = event.data?.latest_build.updated_at !== latestBuildInTimeline.updated_at + if (isUpdated) { return send({ type: "REFRESH_TIMELINE" }) } - }), + } else { + return send({ type: "REFRESH_TIMELINE" }) + } + }), + }, + guards: { + hasMoreBuilds: (_) => false, + }, + services: { + getWorkspace: async (_, event) => { + return await API.getWorkspaceByOwnerAndName(event.username, event.workspaceName, { + include_deleted: true, + }) + }, + getTemplate: async (context) => { + if (context.workspace) { + return await API.getTemplate(context.workspace.template_id) + } else { + throw Error("Cannot get template without workspace") + } + }, + startWorkspace: async (context) => { + if (context.workspace) { + return await API.startWorkspace(context.workspace.id, context.template?.active_version_id) + } else { + throw Error("Cannot start workspace without workspace id") + } }, - guards: { - hasMoreBuilds: (_) => false, + stopWorkspace: async (context) => { + if (context.workspace) { + return await API.stopWorkspace(context.workspace.id) + } else { + throw Error("Cannot stop workspace without workspace id") + } }, - services: { - getWorkspace: async (_, event) => { - return await API.getWorkspaceByOwnerAndName(event.username, event.workspaceName, { - include_deleted: true, + deleteWorkspace: async (context) => { + if (context.workspace) { + return await API.deleteWorkspace(context.workspace.id) + } else { + throw Error("Cannot delete workspace without workspace id") + } + }, + cancelWorkspace: async (context) => { + if (context.workspace) { + return await API.cancelWorkspaceBuild(context.workspace.latest_build.id) + } else { + throw Error("Cannot cancel workspace without build id") + } + }, + refreshWorkspace: async (context) => { + if (context.workspace) { + return await API.getWorkspaceByOwnerAndName( + context.workspace.owner_name, + context.workspace.name, + { + include_deleted: true, + }, + ) + } else { + throw Error("Cannot refresh workspace without id") + } + }, + getResources: async (context) => { + // If the job hasn't completed, fetching resources will result + // in an unfriendly error for the user. + if (!context.workspace?.latest_build.job.completed_at) { + return [] + } + const resources = await API.getWorkspaceResources(context.workspace.latest_build.id) + return resources + }, + getBuilds: async (context) => { + if (context.workspace) { + return await API.getWorkspaceBuilds(context.workspace.id) + } else { + throw Error("Cannot get builds without id") + } + }, + loadMoreBuilds: async (context) => { + if (context.workspace) { + return await API.getWorkspaceBuilds(context.workspace.id) + } else { + throw Error("Cannot load more builds without id") + } + }, + checkPermissions: async (context) => { + if (context.workspace && context.userId) { + return await API.checkUserPermissions(context.userId, { + checks: permissionsToCheck(context.workspace), }) - }, - getTemplate: async (context) => { - if (context.workspace) { - return await API.getTemplate(context.workspace.template_id) - } else { - throw Error("Cannot get template without workspace") - } - }, - startWorkspace: async (context) => { - if (context.workspace) { - return await API.startWorkspace( - context.workspace.id, - context.template?.active_version_id, - ) - } else { - throw Error("Cannot start workspace without workspace id") - } - }, - stopWorkspace: async (context) => { - if (context.workspace) { - return await API.stopWorkspace(context.workspace.id) - } else { - throw Error("Cannot stop workspace without workspace id") - } - }, - deleteWorkspace: async (context) => { - if (context.workspace) { - return await API.deleteWorkspace(context.workspace.id) - } else { - throw Error("Cannot delete workspace without workspace id") - } - }, - cancelWorkspace: async (context) => { - if (context.workspace) { - return await API.cancelWorkspaceBuild(context.workspace.latest_build.id) - } else { - throw Error("Cannot cancel workspace without build id") - } - }, - refreshWorkspace: async (context) => { - if (context.workspace) { - return await API.getWorkspaceByOwnerAndName( - context.workspace.owner_name, - context.workspace.name, - { - include_deleted: true, - }, - ) - } else { - throw Error("Cannot refresh workspace without id") - } - }, - getResources: async (context) => { - // If the job hasn't completed, fetching resources will result - // in an unfriendly error for the user. - if (!context.workspace?.latest_build.job.completed_at) { - return [] - } - const resources = await API.getWorkspaceResources(context.workspace.latest_build.id) - return resources - }, - getBuilds: async (context) => { - if (context.workspace) { - return await API.getWorkspaceBuilds(context.workspace.id) - } else { - throw Error("Cannot get builds without id") - } - }, - loadMoreBuilds: async (context) => { - if (context.workspace) { - return await API.getWorkspaceBuilds(context.workspace.id) - } else { - throw Error("Cannot load more builds without id") - } - }, - checkPermissions: async (context) => { - if (context.workspace && context.userId) { - return await API.checkUserPermissions(context.userId, { - checks: permissionsToCheck(context.workspace), - }) - } else { - throw Error("Cannot check permissions without both workspace and user id") - } - }, + } else { + throw Error("Cannot check permissions without both workspace and user id") + } }, }, - ) + }, +)