mirror of https://github.com/coder/coder.git
chore: update generated array type definitions in TypeScript to be readonly (#12947)
* chore: types generated handling readonly slices * add -update flag to update goldens * revert excess gens * fix: update most UI types to account for readonly modifiers * fix: remove accidental mutation from NavBarView * fix: remove mutation warning for BatchUpdateConfirmation stories * fix: remove mutation warning for BactchUpdateConfirmation * fix: format ActiveUserChart * fix: update import to make linter happy * fix: update fmt issue * fix: disable file write lint rule from unit test --------- Co-authored-by: Parkreiner <throwawayclover@gmail.com>
This commit is contained in:
parent
7cf8577f1c
commit
d9da054c9d
|
@ -814,11 +814,17 @@ func (g *Generator) typescriptType(ty types.Type) (TypescriptType, error) {
|
|||
return TypescriptType{}, xerrors.Errorf("array: %w", err)
|
||||
}
|
||||
genValue := ""
|
||||
|
||||
// Always wrap in parentheses for proper scoped types.
|
||||
// Running prettier on this output will remove redundant parenthesis,
|
||||
// so this makes our decision-making easier.
|
||||
// The example that breaks without this is:
|
||||
// readonly readonly string[][]
|
||||
if underlying.GenericValue != "" {
|
||||
genValue = underlying.GenericValue + "[]"
|
||||
genValue = "(readonly " + underlying.GenericValue + "[])"
|
||||
}
|
||||
return TypescriptType{
|
||||
ValueType: underlying.ValueType + "[]",
|
||||
ValueType: "(readonly " + underlying.ValueType + "[])",
|
||||
GenericValue: genValue,
|
||||
AboveTypeLine: underlying.AboveTypeLine,
|
||||
GenericTypes: underlying.GenericTypes,
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
@ -15,6 +16,9 @@ import (
|
|||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
// updateGoldenFiles is a flag that can be set to update golden files.
|
||||
var updateGoldenFiles = flag.Bool("update", false, "Update golden files")
|
||||
|
||||
func TestGeneration(t *testing.T) {
|
||||
t.Parallel()
|
||||
files, err := os.ReadDir("testdata")
|
||||
|
@ -37,7 +41,13 @@ func TestGeneration(t *testing.T) {
|
|||
require.NoErrorf(t, err, "read file %s", golden)
|
||||
expectedString := strings.TrimSpace(string(expected))
|
||||
output = strings.TrimSpace(output)
|
||||
require.Equal(t, expectedString, output, "matched output")
|
||||
if *updateGoldenFiles {
|
||||
// nolint:gosec
|
||||
err := os.WriteFile(golden, []byte(output), 0o644)
|
||||
require.NoError(t, err, "write golden file")
|
||||
} else {
|
||||
require.Equal(t, expectedString, output, "matched output")
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
package codersdk
|
||||
|
||||
type (
|
||||
Enum string
|
||||
Enums []Enum
|
||||
Enum string
|
||||
EnumSliceType []Enum
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
// From codersdk/enums.go
|
||||
export type Enums = Enum[]
|
||||
export type EnumSliceType = (readonly Enum[])
|
||||
|
||||
// From codersdk/enums.go
|
||||
export type Enum = "bar" | "baz" | "foo" | "qux"
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
package codersdk
|
||||
|
||||
type Foo struct {
|
||||
Bar string `json:"bar"`
|
||||
}
|
||||
|
||||
type Buzz struct {
|
||||
Foo `json:"foo"`
|
||||
Bazz string `json:"bazz"`
|
||||
}
|
||||
|
||||
type Custom interface {
|
||||
Foo | Buzz
|
||||
type Foo struct {
|
||||
Bar string `json:"bar"`
|
||||
}
|
||||
|
||||
type FooBuzz[R Custom] struct {
|
||||
Something []R `json:"something"`
|
||||
}
|
||||
|
||||
type Custom interface {
|
||||
Foo | Buzz
|
||||
}
|
||||
|
||||
// Not yet supported
|
||||
//type FooBuzzMap[R Custom] struct {
|
||||
// Something map[string]R `json:"something"`
|
||||
|
|
|
@ -11,8 +11,8 @@ export interface Foo {
|
|||
|
||||
// From codersdk/genericmap.go
|
||||
export interface FooBuzz<R extends Custom> {
|
||||
readonly something: R[]
|
||||
readonly something: (readonly R[])
|
||||
}
|
||||
|
||||
// From codersdk/genericmap.go
|
||||
export type Custom = Foo | Buzz
|
||||
export type Custom = Foo | Buzz
|
|
@ -33,9 +33,9 @@ export interface Static {
|
|||
}
|
||||
|
||||
// From codersdk/generics.go
|
||||
export type Custom = string | boolean | number | string[] | null
|
||||
export type Custom = string | boolean | number | (readonly string[]) | null
|
||||
|
||||
// From codersdk/generics.go
|
||||
export type Single = string
|
||||
|
||||
export type comparable = boolean | number | string | any
|
||||
export type comparable = boolean | number | string | any
|
|
@ -0,0 +1,10 @@
|
|||
package codersdk
|
||||
|
||||
type Bar struct {
|
||||
Bar string
|
||||
}
|
||||
|
||||
type Foo[R any] struct {
|
||||
Slice []R
|
||||
TwoD [][]R
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
// From codersdk/genericslice.go
|
||||
export interface Bar {
|
||||
readonly Bar: string
|
||||
}
|
||||
|
||||
// From codersdk/genericslice.go
|
||||
export interface Foo<R extends any> {
|
||||
readonly Slice: (readonly R[])
|
||||
readonly TwoD: (readonly (readonly R[])[])
|
||||
}
|
|
@ -4,8 +4,8 @@
|
|||
|
||||
// From codersdk/templates.go
|
||||
export interface ACLAvailable {
|
||||
readonly users: ReducedUser[];
|
||||
readonly groups: Group[];
|
||||
readonly users: readonly ReducedUser[];
|
||||
readonly groups: readonly Group[];
|
||||
}
|
||||
|
||||
// From codersdk/apikey.go
|
||||
|
@ -49,7 +49,7 @@ export interface AppearanceConfig {
|
|||
readonly application_name: string;
|
||||
readonly logo_url: string;
|
||||
readonly service_banner: ServiceBannerConfig;
|
||||
readonly support_links?: LinkConfig[];
|
||||
readonly support_links?: readonly LinkConfig[];
|
||||
}
|
||||
|
||||
// From codersdk/templates.go
|
||||
|
@ -60,7 +60,7 @@ export interface ArchiveTemplateVersionsRequest {
|
|||
// From codersdk/templates.go
|
||||
export interface ArchiveTemplateVersionsResponse {
|
||||
readonly template_id: string;
|
||||
readonly archived_ids: string[];
|
||||
readonly archived_ids: readonly string[];
|
||||
}
|
||||
|
||||
// From codersdk/roles.go
|
||||
|
@ -108,7 +108,7 @@ export interface AuditLog {
|
|||
|
||||
// From codersdk/audit.go
|
||||
export interface AuditLogResponse {
|
||||
readonly audit_logs: AuditLog[];
|
||||
readonly audit_logs: readonly AuditLog[];
|
||||
readonly count: number;
|
||||
}
|
||||
|
||||
|
@ -153,7 +153,7 @@ export type AuthorizationResponse = Record<string, boolean>;
|
|||
|
||||
// From codersdk/deployment.go
|
||||
export interface AvailableExperiments {
|
||||
readonly safe: Experiment[];
|
||||
readonly safe: readonly Experiment[];
|
||||
}
|
||||
|
||||
// From codersdk/deployment.go
|
||||
|
@ -241,8 +241,8 @@ export interface CreateTemplateRequest {
|
|||
// From codersdk/templateversions.go
|
||||
export interface CreateTemplateVersionDryRunRequest {
|
||||
readonly workspace_name: string;
|
||||
readonly rich_parameter_values: WorkspaceBuildParameter[];
|
||||
readonly user_variable_values?: VariableValue[];
|
||||
readonly rich_parameter_values: readonly WorkspaceBuildParameter[];
|
||||
readonly user_variable_values?: readonly VariableValue[];
|
||||
}
|
||||
|
||||
// From codersdk/organizations.go
|
||||
|
@ -255,7 +255,7 @@ export interface CreateTemplateVersionRequest {
|
|||
readonly example_id?: string;
|
||||
readonly provisioner: ProvisionerType;
|
||||
readonly tags: Record<string, string>;
|
||||
readonly user_variable_values?: VariableValue[];
|
||||
readonly user_variable_values?: readonly VariableValue[];
|
||||
}
|
||||
|
||||
// From codersdk/audit.go
|
||||
|
@ -292,7 +292,7 @@ export interface CreateWorkspaceBuildRequest {
|
|||
readonly dry_run?: boolean;
|
||||
readonly state?: string;
|
||||
readonly orphan?: boolean;
|
||||
readonly rich_parameter_values?: WorkspaceBuildParameter[];
|
||||
readonly rich_parameter_values?: readonly WorkspaceBuildParameter[];
|
||||
readonly log_level?: ProvisionerLogLevel;
|
||||
}
|
||||
|
||||
|
@ -310,7 +310,7 @@ export interface CreateWorkspaceRequest {
|
|||
readonly name: string;
|
||||
readonly autostart_schedule?: string;
|
||||
readonly ttl_ms?: number;
|
||||
readonly rich_parameter_values?: WorkspaceBuildParameter[];
|
||||
readonly rich_parameter_values?: readonly WorkspaceBuildParameter[];
|
||||
readonly automatic_updates?: AutomaticUpdates;
|
||||
}
|
||||
|
||||
|
@ -327,7 +327,7 @@ export interface DAURequest {
|
|||
|
||||
// From codersdk/deployment.go
|
||||
export interface DAUsResponse {
|
||||
readonly entries: DAUEntry[];
|
||||
readonly entries: readonly DAUEntry[];
|
||||
readonly tz_hour_offset: number;
|
||||
}
|
||||
|
||||
|
@ -434,7 +434,7 @@ export interface DeploymentValues {
|
|||
readonly session_lifetime?: SessionLifetime;
|
||||
readonly disable_password_auth?: boolean;
|
||||
readonly support?: SupportConfig;
|
||||
readonly external_auth?: ExternalAuthConfig[];
|
||||
readonly external_auth?: readonly ExternalAuthConfig[];
|
||||
readonly config_ssh?: SSHConfig;
|
||||
readonly wgtunnel_host?: string;
|
||||
readonly disable_owner_workspace_exec?: boolean;
|
||||
|
@ -453,8 +453,8 @@ export interface DeploymentValues {
|
|||
// From codersdk/deployment.go
|
||||
export interface Entitlements {
|
||||
readonly features: Record<FeatureName, Feature>;
|
||||
readonly warnings: string[];
|
||||
readonly errors: string[];
|
||||
readonly warnings: readonly string[];
|
||||
readonly errors: readonly string[];
|
||||
readonly has_license: boolean;
|
||||
readonly trial: boolean;
|
||||
readonly require_telemetry: boolean;
|
||||
|
@ -462,7 +462,7 @@ export interface Entitlements {
|
|||
}
|
||||
|
||||
// From codersdk/deployment.go
|
||||
export type Experiments = Experiment[];
|
||||
export type Experiments = readonly Experiment[];
|
||||
|
||||
// From codersdk/externalauth.go
|
||||
export interface ExternalAuth {
|
||||
|
@ -471,7 +471,7 @@ export interface ExternalAuth {
|
|||
readonly display_name: string;
|
||||
readonly user?: ExternalAuthUser;
|
||||
readonly app_installable: boolean;
|
||||
readonly installations: ExternalAuthAppInstallation[];
|
||||
readonly installations: readonly ExternalAuthAppInstallation[];
|
||||
readonly app_install_url: string;
|
||||
}
|
||||
|
||||
|
@ -493,8 +493,8 @@ export interface ExternalAuthConfig {
|
|||
readonly app_install_url: string;
|
||||
readonly app_installations_url: string;
|
||||
readonly no_refresh: boolean;
|
||||
readonly scopes: string[];
|
||||
readonly extra_token_keys: string[];
|
||||
readonly scopes: readonly string[];
|
||||
readonly extra_token_keys: readonly string[];
|
||||
readonly device_flow: boolean;
|
||||
readonly device_code_url: string;
|
||||
readonly regex: string;
|
||||
|
@ -561,7 +561,7 @@ export interface GenerateAPIKeyResponse {
|
|||
|
||||
// From codersdk/users.go
|
||||
export interface GetUsersResponse {
|
||||
readonly users: User[];
|
||||
readonly users: readonly User[];
|
||||
readonly count: number;
|
||||
}
|
||||
|
||||
|
@ -579,7 +579,7 @@ export interface Group {
|
|||
readonly name: string;
|
||||
readonly display_name: string;
|
||||
readonly organization_id: string;
|
||||
readonly members: ReducedUser[];
|
||||
readonly members: readonly ReducedUser[];
|
||||
readonly avatar_url: string;
|
||||
readonly quota_allowance: number;
|
||||
readonly source: GroupSource;
|
||||
|
@ -638,8 +638,8 @@ export interface LinkConfig {
|
|||
|
||||
// From codersdk/externalauth.go
|
||||
export interface ListUserExternalAuthResponse {
|
||||
readonly providers: ExternalAuthLinkProvider[];
|
||||
readonly links: ExternalAuthLink[];
|
||||
readonly providers: readonly ExternalAuthLinkProvider[];
|
||||
readonly links: readonly ExternalAuthLink[];
|
||||
}
|
||||
|
||||
// From codersdk/deployment.go
|
||||
|
@ -753,7 +753,7 @@ export interface OIDCConfig {
|
|||
readonly groups_field: string;
|
||||
readonly group_mapping: Record<string, string>;
|
||||
readonly user_role_field: string;
|
||||
readonly user_role_mapping: Record<string, string[]>;
|
||||
readonly user_role_mapping: Record<string, readonly string[]>;
|
||||
readonly user_roles_default: string[];
|
||||
readonly sign_in_text: string;
|
||||
readonly icon_url: string;
|
||||
|
@ -775,7 +775,7 @@ export interface OrganizationMember {
|
|||
readonly organization_id: string;
|
||||
readonly created_at: string;
|
||||
readonly updated_at: string;
|
||||
readonly roles: Role[];
|
||||
readonly roles: readonly Role[];
|
||||
}
|
||||
|
||||
// From codersdk/pagination.go
|
||||
|
@ -787,8 +787,8 @@ export interface Pagination {
|
|||
|
||||
// From codersdk/groups.go
|
||||
export interface PatchGroupRequest {
|
||||
readonly add_users: string[];
|
||||
readonly remove_users: string[];
|
||||
readonly add_users: readonly string[];
|
||||
readonly remove_users: readonly string[];
|
||||
readonly name: string;
|
||||
readonly display_name?: string;
|
||||
readonly avatar_url?: string;
|
||||
|
@ -850,7 +850,7 @@ export interface ProvisionerDaemon {
|
|||
readonly name: string;
|
||||
readonly version: string;
|
||||
readonly api_version: string;
|
||||
readonly provisioners: ProvisionerType[];
|
||||
readonly provisioners: readonly ProvisionerType[];
|
||||
readonly tags: Record<string, string>;
|
||||
}
|
||||
|
||||
|
@ -883,8 +883,8 @@ export interface ProvisionerJobLog {
|
|||
|
||||
// From codersdk/workspaceproxy.go
|
||||
export interface ProxyHealthReport {
|
||||
readonly errors: string[];
|
||||
readonly warnings: string[];
|
||||
readonly errors: readonly string[];
|
||||
readonly warnings: readonly string[];
|
||||
}
|
||||
|
||||
// From codersdk/workspaces.go
|
||||
|
@ -929,7 +929,7 @@ export interface Region {
|
|||
|
||||
// From codersdk/workspaceproxy.go
|
||||
export interface RegionsResponse<R extends RegionTypes> {
|
||||
readonly regions: R[];
|
||||
readonly regions: readonly R[];
|
||||
}
|
||||
|
||||
// From codersdk/replicas.go
|
||||
|
@ -952,7 +952,7 @@ export interface ResolveAutostartResponse {
|
|||
export interface Response {
|
||||
readonly message: string;
|
||||
readonly detail?: string;
|
||||
readonly validations?: ValidationError[];
|
||||
readonly validations?: readonly ValidationError[];
|
||||
}
|
||||
|
||||
// From codersdk/roles.go
|
||||
|
@ -1005,7 +1005,7 @@ export interface SessionLifetime {
|
|||
|
||||
// From codersdk/deployment.go
|
||||
export interface SupportConfig {
|
||||
readonly links: LinkConfig[];
|
||||
readonly links: readonly LinkConfig[];
|
||||
}
|
||||
|
||||
// From codersdk/deployment.go
|
||||
|
@ -1070,13 +1070,13 @@ export interface Template {
|
|||
|
||||
// From codersdk/templates.go
|
||||
export interface TemplateACL {
|
||||
readonly users: TemplateUser[];
|
||||
readonly group: TemplateGroup[];
|
||||
readonly users: readonly TemplateUser[];
|
||||
readonly group: readonly TemplateGroup[];
|
||||
}
|
||||
|
||||
// From codersdk/insights.go
|
||||
export interface TemplateAppUsage {
|
||||
readonly template_ids: string[];
|
||||
readonly template_ids: readonly string[];
|
||||
readonly type: TemplateAppsType;
|
||||
readonly display_name: string;
|
||||
readonly slug: string;
|
||||
|
@ -1086,12 +1086,12 @@ export interface TemplateAppUsage {
|
|||
|
||||
// From codersdk/templates.go
|
||||
export interface TemplateAutostartRequirement {
|
||||
readonly days_of_week: string[];
|
||||
readonly days_of_week: readonly string[];
|
||||
}
|
||||
|
||||
// From codersdk/templates.go
|
||||
export interface TemplateAutostopRequirement {
|
||||
readonly days_of_week: string[];
|
||||
readonly days_of_week: readonly string[];
|
||||
readonly weeks: number;
|
||||
}
|
||||
|
||||
|
@ -1108,7 +1108,7 @@ export interface TemplateExample {
|
|||
readonly name: string;
|
||||
readonly description: string;
|
||||
readonly icon: string;
|
||||
readonly tags: string[];
|
||||
readonly tags: readonly string[];
|
||||
readonly markdown: string;
|
||||
}
|
||||
|
||||
|
@ -1121,7 +1121,7 @@ export interface TemplateGroup extends Group {
|
|||
export interface TemplateInsightsIntervalReport {
|
||||
readonly start_time: string;
|
||||
readonly end_time: string;
|
||||
readonly template_ids: string[];
|
||||
readonly template_ids: readonly string[];
|
||||
readonly interval: InsightsReportInterval;
|
||||
readonly active_users: number;
|
||||
}
|
||||
|
@ -1130,36 +1130,36 @@ export interface TemplateInsightsIntervalReport {
|
|||
export interface TemplateInsightsReport {
|
||||
readonly start_time: string;
|
||||
readonly end_time: string;
|
||||
readonly template_ids: string[];
|
||||
readonly template_ids: readonly string[];
|
||||
readonly active_users: number;
|
||||
readonly apps_usage: TemplateAppUsage[];
|
||||
readonly parameters_usage: TemplateParameterUsage[];
|
||||
readonly apps_usage: readonly TemplateAppUsage[];
|
||||
readonly parameters_usage: readonly TemplateParameterUsage[];
|
||||
}
|
||||
|
||||
// From codersdk/insights.go
|
||||
export interface TemplateInsightsRequest {
|
||||
readonly start_time: string;
|
||||
readonly end_time: string;
|
||||
readonly template_ids: string[];
|
||||
readonly template_ids: readonly string[];
|
||||
readonly interval: InsightsReportInterval;
|
||||
readonly sections: TemplateInsightsSection[];
|
||||
readonly sections: readonly TemplateInsightsSection[];
|
||||
}
|
||||
|
||||
// From codersdk/insights.go
|
||||
export interface TemplateInsightsResponse {
|
||||
readonly report?: TemplateInsightsReport;
|
||||
readonly interval_reports?: TemplateInsightsIntervalReport[];
|
||||
readonly interval_reports?: readonly TemplateInsightsIntervalReport[];
|
||||
}
|
||||
|
||||
// From codersdk/insights.go
|
||||
export interface TemplateParameterUsage {
|
||||
readonly template_ids: string[];
|
||||
readonly template_ids: readonly string[];
|
||||
readonly display_name: string;
|
||||
readonly name: string;
|
||||
readonly type: string;
|
||||
readonly description: string;
|
||||
readonly options?: TemplateVersionParameterOption[];
|
||||
readonly values: TemplateParameterValue[];
|
||||
readonly options?: readonly TemplateVersionParameterOption[];
|
||||
readonly values: readonly TemplateParameterValue[];
|
||||
}
|
||||
|
||||
// From codersdk/insights.go
|
||||
|
@ -1186,7 +1186,7 @@ export interface TemplateVersion {
|
|||
readonly readme: string;
|
||||
readonly created_by: MinimalUser;
|
||||
readonly archived: boolean;
|
||||
readonly warnings?: TemplateVersionWarning[];
|
||||
readonly warnings?: readonly TemplateVersionWarning[];
|
||||
}
|
||||
|
||||
// From codersdk/templateversions.go
|
||||
|
@ -1210,7 +1210,7 @@ export interface TemplateVersionParameter {
|
|||
readonly mutable: boolean;
|
||||
readonly default_value: string;
|
||||
readonly icon: string;
|
||||
readonly options: TemplateVersionParameterOption[];
|
||||
readonly options: readonly TemplateVersionParameterOption[];
|
||||
readonly validation_error?: string;
|
||||
readonly validation_regex?: string;
|
||||
readonly validation_min?: number;
|
||||
|
@ -1290,7 +1290,7 @@ export interface UpdateCheckResponse {
|
|||
|
||||
// From codersdk/users.go
|
||||
export interface UpdateRoles {
|
||||
readonly roles: string[];
|
||||
readonly roles: readonly string[];
|
||||
}
|
||||
|
||||
// From codersdk/templates.go
|
||||
|
@ -1391,13 +1391,13 @@ export interface UpsertWorkspaceAgentPortShareRequest {
|
|||
|
||||
// From codersdk/users.go
|
||||
export interface User extends ReducedUser {
|
||||
readonly organization_ids: string[];
|
||||
readonly roles: Role[];
|
||||
readonly organization_ids: readonly string[];
|
||||
readonly roles: readonly Role[];
|
||||
}
|
||||
|
||||
// From codersdk/insights.go
|
||||
export interface UserActivity {
|
||||
readonly template_ids: string[];
|
||||
readonly template_ids: readonly string[];
|
||||
readonly user_id: string;
|
||||
readonly username: string;
|
||||
readonly avatar_url: string;
|
||||
|
@ -1408,15 +1408,15 @@ export interface UserActivity {
|
|||
export interface UserActivityInsightsReport {
|
||||
readonly start_time: string;
|
||||
readonly end_time: string;
|
||||
readonly template_ids: string[];
|
||||
readonly users: UserActivity[];
|
||||
readonly template_ids: readonly string[];
|
||||
readonly users: readonly UserActivity[];
|
||||
}
|
||||
|
||||
// From codersdk/insights.go
|
||||
export interface UserActivityInsightsRequest {
|
||||
readonly start_time: string;
|
||||
readonly end_time: string;
|
||||
readonly template_ids: string[];
|
||||
readonly template_ids: readonly string[];
|
||||
}
|
||||
|
||||
// From codersdk/insights.go
|
||||
|
@ -1426,7 +1426,7 @@ export interface UserActivityInsightsResponse {
|
|||
|
||||
// From codersdk/insights.go
|
||||
export interface UserLatency {
|
||||
readonly template_ids: string[];
|
||||
readonly template_ids: readonly string[];
|
||||
readonly user_id: string;
|
||||
readonly username: string;
|
||||
readonly avatar_url: string;
|
||||
|
@ -1437,15 +1437,15 @@ export interface UserLatency {
|
|||
export interface UserLatencyInsightsReport {
|
||||
readonly start_time: string;
|
||||
readonly end_time: string;
|
||||
readonly template_ids: string[];
|
||||
readonly users: UserLatency[];
|
||||
readonly template_ids: readonly string[];
|
||||
readonly users: readonly UserLatency[];
|
||||
}
|
||||
|
||||
// From codersdk/insights.go
|
||||
export interface UserLatencyInsightsRequest {
|
||||
readonly start_time: string;
|
||||
readonly end_time: string;
|
||||
readonly template_ids: string[];
|
||||
readonly template_ids: readonly string[];
|
||||
}
|
||||
|
||||
// From codersdk/insights.go
|
||||
|
@ -1482,8 +1482,8 @@ export interface UserQuietHoursScheduleResponse {
|
|||
|
||||
// From codersdk/users.go
|
||||
export interface UserRoles {
|
||||
readonly roles: string[];
|
||||
readonly organization_roles: Record<string, string[]>;
|
||||
readonly roles: readonly string[];
|
||||
readonly organization_roles: Record<string, readonly string[]>;
|
||||
}
|
||||
|
||||
// From codersdk/users.go
|
||||
|
@ -1557,15 +1557,15 @@ export interface WorkspaceAgent {
|
|||
readonly expanded_directory?: string;
|
||||
readonly version: string;
|
||||
readonly api_version: string;
|
||||
readonly apps: WorkspaceApp[];
|
||||
readonly apps: readonly WorkspaceApp[];
|
||||
readonly latency?: Record<string, DERPRegion>;
|
||||
readonly connection_timeout_seconds: number;
|
||||
readonly troubleshooting_url: string;
|
||||
readonly subsystems: AgentSubsystem[];
|
||||
readonly subsystems: readonly AgentSubsystem[];
|
||||
readonly health: WorkspaceAgentHealth;
|
||||
readonly display_apps: DisplayApp[];
|
||||
readonly log_sources: WorkspaceAgentLogSource[];
|
||||
readonly scripts: WorkspaceAgentScript[];
|
||||
readonly display_apps: readonly DisplayApp[];
|
||||
readonly log_sources: readonly WorkspaceAgentLogSource[];
|
||||
readonly scripts: readonly WorkspaceAgentScript[];
|
||||
readonly startup_script_behavior: WorkspaceAgentStartupScriptBehavior;
|
||||
}
|
||||
|
||||
|
@ -1584,7 +1584,7 @@ export interface WorkspaceAgentListeningPort {
|
|||
|
||||
// From codersdk/workspaceagents.go
|
||||
export interface WorkspaceAgentListeningPortsResponse {
|
||||
readonly ports: WorkspaceAgentListeningPort[];
|
||||
readonly ports: readonly WorkspaceAgentListeningPort[];
|
||||
}
|
||||
|
||||
// From codersdk/workspaceagents.go
|
||||
|
@ -1639,7 +1639,7 @@ export interface WorkspaceAgentPortShare {
|
|||
|
||||
// From codersdk/workspaceagentportshare.go
|
||||
export interface WorkspaceAgentPortShares {
|
||||
readonly shares: WorkspaceAgentPortShare[];
|
||||
readonly shares: readonly WorkspaceAgentPortShare[];
|
||||
}
|
||||
|
||||
// From codersdk/workspaceagents.go
|
||||
|
@ -1688,7 +1688,7 @@ export interface WorkspaceBuild {
|
|||
readonly initiator_name: string;
|
||||
readonly job: ProvisionerJob;
|
||||
readonly reason: BuildReason;
|
||||
readonly resources: WorkspaceResource[];
|
||||
readonly resources: readonly WorkspaceResource[];
|
||||
readonly deadline?: string;
|
||||
readonly max_deadline?: string;
|
||||
readonly status: WorkspaceStatus;
|
||||
|
@ -1732,7 +1732,7 @@ export interface WorkspaceFilter {
|
|||
// From codersdk/workspaces.go
|
||||
export interface WorkspaceHealth {
|
||||
readonly healthy: boolean;
|
||||
readonly failing_agents: string[];
|
||||
readonly failing_agents: readonly string[];
|
||||
}
|
||||
|
||||
// From codersdk/workspaces.go
|
||||
|
@ -1780,8 +1780,8 @@ export interface WorkspaceResource {
|
|||
readonly name: string;
|
||||
readonly hide: boolean;
|
||||
readonly icon: string;
|
||||
readonly agents?: WorkspaceAgent[];
|
||||
readonly metadata?: WorkspaceResourceMetadata[];
|
||||
readonly agents?: readonly WorkspaceAgent[];
|
||||
readonly metadata?: readonly WorkspaceResourceMetadata[];
|
||||
readonly daily_cost: number;
|
||||
}
|
||||
|
||||
|
@ -1799,7 +1799,7 @@ export interface WorkspacesRequest extends Pagination {
|
|||
|
||||
// From codersdk/workspaces.go
|
||||
export interface WorkspacesResponse {
|
||||
readonly workspaces: Workspace[];
|
||||
readonly workspaces: readonly Workspace[];
|
||||
readonly count: number;
|
||||
}
|
||||
|
||||
|
@ -2285,7 +2285,7 @@ export type RegionTypes = Region | WorkspaceProxy;
|
|||
export interface AccessURLReport {
|
||||
readonly healthy: boolean;
|
||||
readonly severity: HealthSeverity;
|
||||
readonly warnings: HealthMessage[];
|
||||
readonly warnings: readonly HealthMessage[];
|
||||
readonly dismissed: boolean;
|
||||
readonly access_url: string;
|
||||
readonly reachable: boolean;
|
||||
|
@ -2298,14 +2298,14 @@ export interface AccessURLReport {
|
|||
export interface DERPHealthReport {
|
||||
readonly healthy: boolean;
|
||||
readonly severity: HealthSeverity;
|
||||
readonly warnings: HealthMessage[];
|
||||
readonly warnings: readonly HealthMessage[];
|
||||
readonly dismissed: boolean;
|
||||
readonly regions: Record<number, DERPRegionReport>;
|
||||
// Named type "tailscale.com/net/netcheck.Report" unknown, using "any"
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type
|
||||
readonly netcheck?: any;
|
||||
readonly netcheck_err?: string;
|
||||
readonly netcheck_logs: string[];
|
||||
readonly netcheck_logs: readonly string[];
|
||||
readonly error?: string;
|
||||
}
|
||||
|
||||
|
@ -2313,7 +2313,7 @@ export interface DERPHealthReport {
|
|||
export interface DERPNodeReport {
|
||||
readonly healthy: boolean;
|
||||
readonly severity: HealthSeverity;
|
||||
readonly warnings: HealthMessage[];
|
||||
readonly warnings: readonly HealthMessage[];
|
||||
// Named type "tailscale.com/tailcfg.DERPNode" unknown, using "any"
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type
|
||||
readonly node?: any;
|
||||
|
@ -2324,8 +2324,8 @@ export interface DERPNodeReport {
|
|||
readonly round_trip_ping: string;
|
||||
readonly round_trip_ping_ms: number;
|
||||
readonly uses_websocket: boolean;
|
||||
readonly client_logs: string[][];
|
||||
readonly client_errs: string[][];
|
||||
readonly client_logs: readonly (readonly string[])[];
|
||||
readonly client_errs: readonly (readonly string[])[];
|
||||
readonly error?: string;
|
||||
readonly stun: STUNReport;
|
||||
}
|
||||
|
@ -2334,11 +2334,11 @@ export interface DERPNodeReport {
|
|||
export interface DERPRegionReport {
|
||||
readonly healthy: boolean;
|
||||
readonly severity: HealthSeverity;
|
||||
readonly warnings: HealthMessage[];
|
||||
readonly warnings: readonly HealthMessage[];
|
||||
// Named type "tailscale.com/tailcfg.DERPRegion" unknown, using "any"
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- External type
|
||||
readonly region?: any;
|
||||
readonly node_reports: DERPNodeReport[];
|
||||
readonly node_reports: readonly DERPNodeReport[];
|
||||
readonly error?: string;
|
||||
}
|
||||
|
||||
|
@ -2346,7 +2346,7 @@ export interface DERPRegionReport {
|
|||
export interface DatabaseReport {
|
||||
readonly healthy: boolean;
|
||||
readonly severity: HealthSeverity;
|
||||
readonly warnings: HealthMessage[];
|
||||
readonly warnings: readonly HealthMessage[];
|
||||
readonly dismissed: boolean;
|
||||
readonly reachable: boolean;
|
||||
readonly latency: string;
|
||||
|
@ -2357,7 +2357,7 @@ export interface DatabaseReport {
|
|||
|
||||
// From healthsdk/healthsdk.go
|
||||
export interface HealthSettings {
|
||||
readonly dismissed_healthchecks: HealthSection[];
|
||||
readonly dismissed_healthchecks: readonly HealthSection[];
|
||||
}
|
||||
|
||||
// From healthsdk/healthsdk.go
|
||||
|
@ -2365,7 +2365,7 @@ export interface HealthcheckReport {
|
|||
readonly time: string;
|
||||
readonly healthy: boolean;
|
||||
readonly severity: HealthSeverity;
|
||||
readonly failing_sections: HealthSection[];
|
||||
readonly failing_sections: readonly HealthSection[];
|
||||
readonly derp: DERPHealthReport;
|
||||
readonly access_url: AccessURLReport;
|
||||
readonly websocket: WebsocketReport;
|
||||
|
@ -2378,16 +2378,16 @@ export interface HealthcheckReport {
|
|||
// From healthsdk/healthsdk.go
|
||||
export interface ProvisionerDaemonsReport {
|
||||
readonly severity: HealthSeverity;
|
||||
readonly warnings: HealthMessage[];
|
||||
readonly warnings: readonly HealthMessage[];
|
||||
readonly dismissed: boolean;
|
||||
readonly error?: string;
|
||||
readonly items: ProvisionerDaemonsReportItem[];
|
||||
readonly items: readonly ProvisionerDaemonsReportItem[];
|
||||
}
|
||||
|
||||
// From healthsdk/healthsdk.go
|
||||
export interface ProvisionerDaemonsReportItem {
|
||||
readonly provisioner_daemon: ProvisionerDaemon;
|
||||
readonly warnings: HealthMessage[];
|
||||
readonly warnings: readonly HealthMessage[];
|
||||
}
|
||||
|
||||
// From healthsdk/healthsdk.go
|
||||
|
@ -2399,14 +2399,14 @@ export interface STUNReport {
|
|||
|
||||
// From healthsdk/healthsdk.go
|
||||
export interface UpdateHealthSettings {
|
||||
readonly dismissed_healthchecks: HealthSection[];
|
||||
readonly dismissed_healthchecks: readonly HealthSection[];
|
||||
}
|
||||
|
||||
// From healthsdk/healthsdk.go
|
||||
export interface WebsocketReport {
|
||||
readonly healthy: boolean;
|
||||
readonly severity: HealthSeverity;
|
||||
readonly warnings: string[];
|
||||
readonly warnings: readonly string[];
|
||||
readonly dismissed: boolean;
|
||||
readonly body: string;
|
||||
readonly code: number;
|
||||
|
@ -2417,7 +2417,7 @@ export interface WebsocketReport {
|
|||
export interface WorkspaceProxyReport {
|
||||
readonly healthy: boolean;
|
||||
readonly severity: HealthSeverity;
|
||||
readonly warnings: HealthMessage[];
|
||||
readonly warnings: readonly HealthMessage[];
|
||||
readonly dismissed: boolean;
|
||||
readonly error?: string;
|
||||
readonly workspace_proxies: RegionsResponse<WorkspaceProxy>;
|
||||
|
@ -2520,13 +2520,13 @@ export interface SerpentOption {
|
|||
readonly value?: any;
|
||||
readonly annotations?: SerpentAnnotations;
|
||||
readonly group?: SerpentGroup;
|
||||
readonly use_instead?: SerpentOption[];
|
||||
readonly use_instead?: readonly SerpentOption[];
|
||||
readonly hidden?: boolean;
|
||||
readonly value_source?: SerpentValueSource;
|
||||
}
|
||||
|
||||
// From serpent/option.go
|
||||
export type SerpentOptionSet = SerpentOption[];
|
||||
export type SerpentOptionSet = readonly SerpentOption[];
|
||||
|
||||
// From serpent/option.go
|
||||
export type SerpentValueSource = "" | "default" | "env" | "flag" | "yaml";
|
||||
|
|
|
@ -42,7 +42,7 @@ ChartJS.register(
|
|||
const USER_LIMIT_DISPLAY_THRESHOLD = 60;
|
||||
|
||||
export interface ActiveUserChartProps {
|
||||
data: Array<{ date: string; amount: number }>;
|
||||
data: readonly { date: string; amount: number }[];
|
||||
interval: "day" | "week";
|
||||
userLimit: number | undefined;
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import { TimelineDateRow } from "components/Timeline/TimelineDateRow";
|
|||
type GetDateFn<TData> = (data: TData) => Date;
|
||||
|
||||
const groupByDate = <TData,>(
|
||||
items: TData[],
|
||||
items: readonly TData[],
|
||||
getDate: GetDateFn<TData>,
|
||||
): Record<string, TData[]> => {
|
||||
const itemsByDate: Record<string, TData[]> = {};
|
||||
|
@ -23,7 +23,7 @@ const groupByDate = <TData,>(
|
|||
};
|
||||
|
||||
export interface TimelineProps<TData> {
|
||||
items: TData[];
|
||||
items: readonly TData[];
|
||||
getDate: GetDateFn<TData>;
|
||||
row: (item: TData) => JSX.Element;
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ export interface ProxyContextValue {
|
|||
// WorkspaceProxy[] is returned if the user is an admin. WorkspaceProxy extends Region with
|
||||
// more information about the proxy and the status. More information includes the error message if
|
||||
// the proxy is unhealthy.
|
||||
proxies?: Region[] | WorkspaceProxy[];
|
||||
proxies?: readonly Region[] | readonly WorkspaceProxy[];
|
||||
// isFetched is true when the 'proxies' api call is complete.
|
||||
isFetched: boolean;
|
||||
isLoading: boolean;
|
||||
|
@ -117,7 +117,7 @@ export const ProxyProvider: FC<PropsWithChildren> = ({ children }) => {
|
|||
});
|
||||
|
||||
const { permissions } = useAuthenticated();
|
||||
const query = async (): Promise<Region[]> => {
|
||||
const query = async (): Promise<readonly Region[]> => {
|
||||
const endpoint = permissions.editWorkspaceProxies
|
||||
? getWorkspaceProxies
|
||||
: getWorkspaceProxyRegions;
|
||||
|
@ -218,7 +218,7 @@ export const useProxy = (): ProxyContextValue => {
|
|||
* If not, `primary` is always the best default.
|
||||
*/
|
||||
export const getPreferredProxy = (
|
||||
proxies: Region[],
|
||||
proxies: readonly Region[],
|
||||
selectedProxy?: Region,
|
||||
latencies?: Record<string, ProxyLatencyReport>,
|
||||
autoSelectBasedOnLatency = true,
|
||||
|
@ -245,7 +245,7 @@ export const getPreferredProxy = (
|
|||
};
|
||||
|
||||
const selectByLatency = (
|
||||
proxies: Region[],
|
||||
proxies: readonly Region[],
|
||||
latencies?: Record<string, ProxyLatencyReport>,
|
||||
): Region | undefined => {
|
||||
if (!latencies) {
|
||||
|
|
|
@ -37,7 +37,7 @@ const proxyLatenciesReducer = (
|
|||
};
|
||||
|
||||
export const useProxyLatency = (
|
||||
proxies?: Region[],
|
||||
proxies?: readonly Region[],
|
||||
): {
|
||||
// Refetch can be called to refetch the proxy latencies.
|
||||
// Until the new values are loaded, the old values will still be used.
|
||||
|
@ -265,7 +265,7 @@ const updateStoredLatencies = (action: ProxyLatencyAction): void => {
|
|||
// garbageCollectStoredLatencies will remove any latencies that are older then 1 week or latencies of proxies
|
||||
// that no longer exist. This is intended to keep the size of local storage down.
|
||||
const garbageCollectStoredLatencies = (
|
||||
regions: Region[],
|
||||
regions: readonly Region[],
|
||||
maxStored: number,
|
||||
): void => {
|
||||
const latencies = loadStoredLatencies();
|
||||
|
@ -282,7 +282,7 @@ const garbageCollectStoredLatencies = (
|
|||
|
||||
const cleanupLatencies = (
|
||||
stored: Record<string, ProxyLatencyReport[]>,
|
||||
regions: Region[],
|
||||
regions: readonly Region[],
|
||||
now: Date,
|
||||
maxStored: number,
|
||||
): Record<string, ProxyLatencyReport[]> => {
|
||||
|
|
|
@ -27,8 +27,8 @@ const styles = {
|
|||
} satisfies Record<string, Interpolation<Theme>>;
|
||||
|
||||
export interface LicenseBannerViewProps {
|
||||
errors: string[];
|
||||
warnings: string[];
|
||||
errors: readonly string[];
|
||||
warnings: readonly string[];
|
||||
}
|
||||
|
||||
export const LicenseBannerView: FC<LicenseBannerViewProps> = ({
|
||||
|
|
|
@ -30,7 +30,7 @@ export interface NavbarViewProps {
|
|||
logo_url?: string;
|
||||
user?: TypesGen.User;
|
||||
buildInfo?: TypesGen.BuildInfoResponse;
|
||||
supportLinks?: TypesGen.LinkConfig[];
|
||||
supportLinks?: readonly TypesGen.LinkConfig[];
|
||||
onSignOut: () => void;
|
||||
canViewAuditLog: boolean;
|
||||
canViewDeployment: boolean;
|
||||
|
@ -342,57 +342,58 @@ const ProxyMenu: FC<ProxyMenuProps> = ({ proxyContextValue }) => {
|
|||
|
||||
<Divider css={{ borderColor: theme.palette.divider }} />
|
||||
|
||||
{proxyContextValue.proxies
|
||||
?.sort((a, b) => {
|
||||
const latencyA = latencies?.[a.id]?.latencyMS ?? Infinity;
|
||||
const latencyB = latencies?.[b.id]?.latencyMS ?? Infinity;
|
||||
return latencyA - latencyB;
|
||||
})
|
||||
.map((proxy) => (
|
||||
<MenuItem
|
||||
key={proxy.id}
|
||||
selected={proxy.id === selectedProxy?.id}
|
||||
css={{ fontSize: 14 }}
|
||||
onClick={() => {
|
||||
if (!proxy.healthy) {
|
||||
displayError("Please select a healthy workspace proxy.");
|
||||
closeMenu();
|
||||
return;
|
||||
}
|
||||
{proxyContextValue.proxies &&
|
||||
[...proxyContextValue.proxies]
|
||||
.sort((a, b) => {
|
||||
const latencyA = latencies?.[a.id]?.latencyMS ?? Infinity;
|
||||
const latencyB = latencies?.[b.id]?.latencyMS ?? Infinity;
|
||||
return latencyA - latencyB;
|
||||
})
|
||||
.map((proxy) => (
|
||||
<MenuItem
|
||||
key={proxy.id}
|
||||
selected={proxy.id === selectedProxy?.id}
|
||||
css={{ fontSize: 14 }}
|
||||
onClick={() => {
|
||||
if (!proxy.healthy) {
|
||||
displayError("Please select a healthy workspace proxy.");
|
||||
closeMenu();
|
||||
return;
|
||||
}
|
||||
|
||||
proxyContextValue.setProxy(proxy);
|
||||
closeMenu();
|
||||
}}
|
||||
>
|
||||
<div
|
||||
css={{
|
||||
display: "flex",
|
||||
gap: 24,
|
||||
alignItems: "center",
|
||||
width: "100%",
|
||||
proxyContextValue.setProxy(proxy);
|
||||
closeMenu();
|
||||
}}
|
||||
>
|
||||
<div css={{ width: 14, height: 14, lineHeight: 0 }}>
|
||||
<img
|
||||
src={proxy.icon_url}
|
||||
alt=""
|
||||
css={{
|
||||
objectFit: "contain",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
}}
|
||||
<div
|
||||
css={{
|
||||
display: "flex",
|
||||
gap: 24,
|
||||
alignItems: "center",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<div css={{ width: 14, height: 14, lineHeight: 0 }}>
|
||||
<img
|
||||
src={proxy.icon_url}
|
||||
alt=""
|
||||
css={{
|
||||
objectFit: "contain",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{proxy.display_name}
|
||||
|
||||
<Latency
|
||||
latency={latencies?.[proxy.id]?.latencyMS}
|
||||
isLoading={proxyLatencyLoading(proxy)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{proxy.display_name}
|
||||
|
||||
<Latency
|
||||
latency={latencies?.[proxy.id]?.latencyMS}
|
||||
isLoading={proxyLatencyLoading(proxy)}
|
||||
/>
|
||||
</div>
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuItem>
|
||||
))}
|
||||
|
||||
<Divider css={{ borderColor: theme.palette.divider }} />
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@ import { UserDropdownContent } from "./UserDropdownContent";
|
|||
export interface UserDropdownProps {
|
||||
user: TypesGen.User;
|
||||
buildInfo?: TypesGen.BuildInfoResponse;
|
||||
supportLinks?: TypesGen.LinkConfig[];
|
||||
supportLinks?: readonly TypesGen.LinkConfig[];
|
||||
onSignOut: () => void;
|
||||
children?: ReactNode;
|
||||
}
|
||||
|
|
|
@ -83,7 +83,7 @@ const styles = {
|
|||
export interface UserDropdownContentProps {
|
||||
user: TypesGen.User;
|
||||
buildInfo?: TypesGen.BuildInfoResponse;
|
||||
supportLinks?: TypesGen.LinkConfig[];
|
||||
supportLinks?: readonly TypesGen.LinkConfig[];
|
||||
onSignOut: () => void;
|
||||
}
|
||||
|
||||
|
|
|
@ -20,8 +20,8 @@ type AgentLogsProps = Omit<
|
|||
ComponentProps<typeof List>,
|
||||
"children" | "itemSize" | "itemCount"
|
||||
> & {
|
||||
logs: LineWithID[];
|
||||
sources: WorkspaceAgentLogSource[];
|
||||
logs: readonly LineWithID[];
|
||||
sources: readonly WorkspaceAgentLogSource[];
|
||||
};
|
||||
|
||||
export const AgentLogs = forwardRef<List, AgentLogsProps>(
|
||||
|
|
|
@ -116,7 +116,7 @@ const getValidationSchema = (): Yup.AnyObjectSchema =>
|
|||
});
|
||||
|
||||
interface PortForwardPopoverViewProps extends PortForwardButtonProps {
|
||||
listeningPorts?: WorkspaceAgentListeningPort[];
|
||||
listeningPorts?: readonly WorkspaceAgentListeningPort[];
|
||||
portSharingExperimentEnabled: boolean;
|
||||
portSharingControlsEnabled: boolean;
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ export interface VSCodeDesktopButtonProps {
|
|||
workspaceName: string;
|
||||
agentName?: string;
|
||||
folderPath?: string;
|
||||
displayApps: DisplayApp[];
|
||||
displayApps: readonly DisplayApp[];
|
||||
}
|
||||
|
||||
type VSCodeVariant = "vscode" | "vscode-insiders";
|
||||
|
|
|
@ -32,7 +32,7 @@ export const Language = {
|
|||
};
|
||||
|
||||
export interface AuditPageViewProps {
|
||||
auditLogs?: AuditLog[];
|
||||
auditLogs?: readonly AuditLog[];
|
||||
isNonInitialPage: boolean;
|
||||
isAuditLogVisible: boolean;
|
||||
error?: unknown;
|
||||
|
|
|
@ -17,8 +17,8 @@ import {
|
|||
import { optionValue } from "./optionValue";
|
||||
|
||||
interface OptionsTableProps {
|
||||
options: SerpentOption[];
|
||||
additionalValues?: string[];
|
||||
options: readonly SerpentOption[];
|
||||
additionalValues?: readonly string[];
|
||||
}
|
||||
|
||||
const OptionsTable: FC<OptionsTableProps> = ({ options, additionalValues }) => {
|
||||
|
|
|
@ -4,7 +4,7 @@ import type { SerpentOption } from "api/typesGenerated";
|
|||
// optionValue is a helper function to format the value of a specific deployment options
|
||||
export function optionValue(
|
||||
option: SerpentOption,
|
||||
additionalValues?: string[],
|
||||
additionalValues?: readonly string[],
|
||||
) {
|
||||
// If option annotations are present, use them to format the value.
|
||||
if (option.annotations) {
|
||||
|
|
|
@ -214,7 +214,7 @@ export const BooleanPill: FC<BooleanPillProps> = ({
|
|||
);
|
||||
};
|
||||
|
||||
type LogsProps = { lines: string[] } & HTMLAttributes<HTMLDivElement>;
|
||||
type LogsProps = HTMLAttributes<HTMLDivElement> & { lines: readonly string[] };
|
||||
|
||||
export const Logs: FC<LogsProps> = ({ lines, ...divProps }) => {
|
||||
const theme = useTheme();
|
||||
|
|
|
@ -296,7 +296,7 @@ const UsersLatencyPanel: FC<UsersLatencyPanelProps> = ({
|
|||
{!data && <Loader css={{ height: "100%" }} />}
|
||||
{users && users.length === 0 && <NoDataAvailable />}
|
||||
{users &&
|
||||
users
|
||||
[...users]
|
||||
.sort((a, b) => b.latency_ms.p50 - a.latency_ms.p50)
|
||||
.map((row) => (
|
||||
<div
|
||||
|
@ -367,7 +367,7 @@ const UsersActivityPanel: FC<UsersActivityPanelProps> = ({
|
|||
{!data && <Loader css={{ height: "100%" }} />}
|
||||
{users && users.length === 0 && <NoDataAvailable />}
|
||||
{users &&
|
||||
users
|
||||
[...users]
|
||||
.sort((a, b) => b.seconds - a.seconds)
|
||||
.map((row) => (
|
||||
<div
|
||||
|
@ -405,7 +405,7 @@ const UsersActivityPanel: FC<UsersActivityPanelProps> = ({
|
|||
};
|
||||
|
||||
interface TemplateUsagePanelProps extends PanelProps {
|
||||
data: TemplateAppUsage[] | undefined;
|
||||
data: readonly TemplateAppUsage[] | undefined;
|
||||
}
|
||||
|
||||
const TemplateUsagePanel: FC<TemplateUsagePanelProps> = ({
|
||||
|
@ -508,7 +508,7 @@ const TemplateUsagePanel: FC<TemplateUsagePanelProps> = ({
|
|||
};
|
||||
|
||||
interface TemplateParametersUsagePanelProps extends PanelProps {
|
||||
data: TemplateParameterUsage[] | undefined;
|
||||
data: readonly TemplateParameterUsage[] | undefined;
|
||||
}
|
||||
|
||||
const TemplateParametersUsagePanel: FC<TemplateParametersUsagePanelProps> = ({
|
||||
|
@ -579,7 +579,7 @@ const TemplateParametersUsagePanel: FC<TemplateParametersUsagePanelProps> = ({
|
|||
<div>Count</div>
|
||||
</Tooltip>
|
||||
</ParameterUsageRow>
|
||||
{parameter.values
|
||||
{[...parameter.values]
|
||||
.sort((a, b) => b.count - a.count)
|
||||
.filter((usage) => filterOrphanValues(usage, parameter))
|
||||
.map((usage, usageIndex) => (
|
||||
|
|
|
@ -113,7 +113,7 @@ const ProxyMessagesRow: FC<ProxyMessagesRowProps> = ({ proxy }) => {
|
|||
|
||||
interface ProxyMessagesListProps {
|
||||
title: ReactNode;
|
||||
messages?: string[];
|
||||
messages?: readonly string[];
|
||||
}
|
||||
|
||||
const ProxyMessagesList: FC<ProxyMessagesListProps> = ({ title, messages }) => {
|
||||
|
|
|
@ -15,7 +15,7 @@ import type { ProxyLatencyReport } from "contexts/useProxyLatency";
|
|||
import { ProxyRow } from "./WorkspaceProxyRow";
|
||||
|
||||
export interface WorkspaceProxyViewProps {
|
||||
proxies?: Region[];
|
||||
proxies?: readonly Region[];
|
||||
proxyLatencies?: Record<string, ProxyLatencyReport>;
|
||||
getWorkspaceProxiesError?: unknown;
|
||||
isLoading: boolean;
|
||||
|
|
|
@ -9,7 +9,7 @@ import { UsersFilter } from "./UsersFilter";
|
|||
import { UsersTable } from "./UsersTable/UsersTable";
|
||||
|
||||
export interface UsersPageViewProps {
|
||||
users?: TypesGen.User[];
|
||||
users?: readonly TypesGen.User[];
|
||||
roles?: TypesGen.AssignableRoles[];
|
||||
isUpdatingUserRoles?: boolean;
|
||||
canEditUsers: boolean;
|
||||
|
|
|
@ -69,7 +69,7 @@ const Option: FC<OptionProps> = ({
|
|||
|
||||
export interface EditRolesButtonProps {
|
||||
isLoading: boolean;
|
||||
roles: Role[];
|
||||
roles: readonly Role[];
|
||||
selectedRoleNames: Set<string>;
|
||||
onChange: (roles: Role["name"][]) => void;
|
||||
isDefaultOpen?: boolean;
|
||||
|
|
|
@ -160,7 +160,7 @@ const roleNamesByAccessLevel: readonly string[] = [
|
|||
"auditor",
|
||||
];
|
||||
|
||||
function sortRolesByAccessLevel(roles: Role[]) {
|
||||
function sortRolesByAccessLevel(roles: readonly Role[]): readonly Role[] {
|
||||
if (roles.length === 0) {
|
||||
return roles;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ export const Language = {
|
|||
} as const;
|
||||
|
||||
export interface UsersTableProps {
|
||||
users: TypesGen.User[] | undefined;
|
||||
users: readonly TypesGen.User[] | undefined;
|
||||
roles: TypesGen.AssignableRoles[] | undefined;
|
||||
groupsByUserId: GroupsByUserId | undefined;
|
||||
isUpdatingUserRoles?: boolean;
|
||||
|
|
|
@ -36,7 +36,7 @@ import { UserRoleCell } from "./UserRoleCell";
|
|||
dayjs.extend(relativeTime);
|
||||
|
||||
interface UsersTableBodyProps {
|
||||
users: TypesGen.User[] | undefined;
|
||||
users: readonly TypesGen.User[] | undefined;
|
||||
groupsByUserId: GroupsByUserId | undefined;
|
||||
authMethods?: TypesGen.AuthMethods;
|
||||
roles?: TypesGen.AssignableRoles[];
|
||||
|
|
|
@ -13,7 +13,7 @@ import { getResourceIconPath } from "utils/workspace";
|
|||
dayjs.extend(relativeTime);
|
||||
|
||||
type BatchDeleteConfirmationProps = {
|
||||
checkedWorkspaces: Workspace[];
|
||||
checkedWorkspaces: readonly Workspace[];
|
||||
open: boolean;
|
||||
isLoading: boolean;
|
||||
onClose: () => void;
|
||||
|
@ -111,7 +111,7 @@ export const BatchDeleteConfirmation: FC<BatchDeleteConfirmationProps> = ({
|
|||
};
|
||||
|
||||
interface StageProps {
|
||||
workspaces: Workspace[];
|
||||
workspaces: readonly Workspace[];
|
||||
}
|
||||
|
||||
const Consequences: FC = () => {
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
import { action } from "@storybook/addon-actions";
|
||||
import type { Meta, StoryObj } from "@storybook/react";
|
||||
import { useQueryClient } from "react-query";
|
||||
import type { Workspace } from "api/typesGenerated";
|
||||
import { chromatic } from "testHelpers/chromatic";
|
||||
import {
|
||||
MockWorkspace,
|
||||
|
@ -29,23 +30,33 @@ const workspaces = [
|
|||
},
|
||||
];
|
||||
|
||||
const updates = new Map<string, Update>();
|
||||
for (const it of workspaces) {
|
||||
const versionId = it.template_active_version_id;
|
||||
const version = updates.get(versionId);
|
||||
function getPopulatedUpdates(): Map<string, Update> {
|
||||
type MutableUpdate = Omit<Update, "affected_workspaces"> & {
|
||||
affected_workspaces: Workspace[];
|
||||
};
|
||||
|
||||
if (version) {
|
||||
version.affected_workspaces.push(it);
|
||||
continue;
|
||||
const updates = new Map<string, MutableUpdate>();
|
||||
for (const it of workspaces) {
|
||||
const versionId = it.template_active_version_id;
|
||||
const version = updates.get(versionId);
|
||||
|
||||
if (version) {
|
||||
version.affected_workspaces.push(it);
|
||||
continue;
|
||||
}
|
||||
|
||||
updates.set(versionId, {
|
||||
...MockTemplateVersion,
|
||||
template_display_name: it.template_display_name,
|
||||
affected_workspaces: [it],
|
||||
});
|
||||
}
|
||||
|
||||
updates.set(versionId, {
|
||||
...MockTemplateVersion,
|
||||
template_display_name: it.template_display_name,
|
||||
affected_workspaces: [it],
|
||||
});
|
||||
return updates as Map<string, Update>;
|
||||
}
|
||||
|
||||
const updates = getPopulatedUpdates();
|
||||
|
||||
const meta: Meta<typeof BatchUpdateConfirmation> = {
|
||||
title: "pages/WorkspacesPage/BatchUpdateConfirmation",
|
||||
parameters: { chromatic },
|
||||
|
|
|
@ -18,7 +18,7 @@ import { Stack } from "components/Stack/Stack";
|
|||
dayjs.extend(relativeTime);
|
||||
|
||||
type BatchUpdateConfirmationProps = {
|
||||
checkedWorkspaces: Workspace[];
|
||||
checkedWorkspaces: readonly Workspace[];
|
||||
open: boolean;
|
||||
isLoading: boolean;
|
||||
onClose: () => void;
|
||||
|
@ -27,7 +27,7 @@ type BatchUpdateConfirmationProps = {
|
|||
|
||||
export interface Update extends TemplateVersion {
|
||||
template_display_name: string;
|
||||
affected_workspaces: Workspace[];
|
||||
affected_workspaces: readonly Workspace[];
|
||||
}
|
||||
|
||||
export const BatchUpdateConfirmation: FC<BatchUpdateConfirmationProps> = ({
|
||||
|
@ -90,11 +90,13 @@ export const BatchUpdateConfirmation: FC<BatchUpdateConfirmationProps> = ({
|
|||
// Figure out which new versions everything will be updated to so that we can
|
||||
// show update messages and such.
|
||||
const newVersions = useMemo(() => {
|
||||
const newVersions = new Map<
|
||||
string,
|
||||
Pick<Update, "id" | "template_display_name" | "affected_workspaces">
|
||||
>();
|
||||
type MutableUpdateInfo = {
|
||||
id: string;
|
||||
template_display_name: string;
|
||||
affected_workspaces: Workspace[];
|
||||
};
|
||||
|
||||
const newVersions = new Map<string, MutableUpdateInfo>();
|
||||
for (const it of workspacesToUpdate) {
|
||||
const versionId = it.template_active_version_id;
|
||||
const version = newVersions.get(versionId);
|
||||
|
@ -111,7 +113,11 @@ export const BatchUpdateConfirmation: FC<BatchUpdateConfirmationProps> = ({
|
|||
});
|
||||
}
|
||||
|
||||
return newVersions;
|
||||
type ReadonlyUpdateInfo = Readonly<MutableUpdateInfo> & {
|
||||
affected_workspaces: readonly Workspace[];
|
||||
};
|
||||
|
||||
return newVersions as Map<string, ReadonlyUpdateInfo>;
|
||||
}, [workspacesToUpdate]);
|
||||
|
||||
// Not all of the information we want is included in the `Workspace` type, so we
|
||||
|
@ -401,7 +407,7 @@ const TemplateVersionMessages: FC<TemplateVersionMessagesProps> = ({
|
|||
};
|
||||
|
||||
interface UsedByProps {
|
||||
workspaces: Workspace[];
|
||||
workspaces: readonly Workspace[];
|
||||
}
|
||||
|
||||
const UsedBy: FC<UsedByProps> = ({ workspaces }) => {
|
||||
|
|
|
@ -54,7 +54,9 @@ const WorkspacesPage: FC = () => {
|
|||
});
|
||||
|
||||
const updateWorkspace = useWorkspaceUpdate(queryKey);
|
||||
const [checkedWorkspaces, setCheckedWorkspaces] = useState<Workspace[]>([]);
|
||||
const [checkedWorkspaces, setCheckedWorkspaces] = useState<
|
||||
readonly Workspace[]
|
||||
>([]);
|
||||
const [confirmingBatchAction, setConfirmingBatchAction] = useState<
|
||||
"delete" | "update" | null
|
||||
>(null);
|
||||
|
|
|
@ -44,15 +44,15 @@ type TemplateQuery = UseQueryResult<Template[]>;
|
|||
|
||||
export interface WorkspacesPageViewProps {
|
||||
error: unknown;
|
||||
workspaces?: Workspace[];
|
||||
checkedWorkspaces: Workspace[];
|
||||
workspaces?: readonly Workspace[];
|
||||
checkedWorkspaces: readonly Workspace[];
|
||||
count?: number;
|
||||
filterProps: ComponentProps<typeof WorkspacesFilter>;
|
||||
page: number;
|
||||
limit: number;
|
||||
onPageChange: (page: number) => void;
|
||||
onUpdateWorkspace: (workspace: Workspace) => void;
|
||||
onCheckChange: (checkedWorkspaces: Workspace[]) => void;
|
||||
onCheckChange: (checkedWorkspaces: readonly Workspace[]) => void;
|
||||
isRunningBatchAction: boolean;
|
||||
onDeleteAll: () => void;
|
||||
onUpdateAll: () => void;
|
||||
|
|
|
@ -30,12 +30,12 @@ import { getDisplayWorkspaceTemplateName } from "utils/workspace";
|
|||
import { WorkspacesEmpty } from "./WorkspacesEmpty";
|
||||
|
||||
export interface WorkspacesTableProps {
|
||||
workspaces?: Workspace[];
|
||||
checkedWorkspaces: Workspace[];
|
||||
workspaces?: readonly Workspace[];
|
||||
checkedWorkspaces: readonly Workspace[];
|
||||
error?: unknown;
|
||||
isUsingFilter: boolean;
|
||||
onUpdateWorkspace: (workspace: Workspace) => void;
|
||||
onCheckChange: (checkedWorkspaces: Workspace[]) => void;
|
||||
onCheckChange: (checkedWorkspaces: readonly Workspace[]) => void;
|
||||
canCheckWorkspaces: boolean;
|
||||
templates?: Template[];
|
||||
canCreateTemplate: boolean;
|
||||
|
|
|
@ -18,7 +18,7 @@ export function useBatchActions(options: UseBatchActionsProps) {
|
|||
const { onSuccess } = options;
|
||||
|
||||
const startAllMutation = useMutation({
|
||||
mutationFn: (workspaces: Workspace[]) => {
|
||||
mutationFn: (workspaces: readonly Workspace[]) => {
|
||||
return Promise.all(
|
||||
workspaces.map((w) =>
|
||||
startWorkspace(w.id, w.latest_build.template_version_id),
|
||||
|
@ -32,7 +32,7 @@ export function useBatchActions(options: UseBatchActionsProps) {
|
|||
});
|
||||
|
||||
const stopAllMutation = useMutation({
|
||||
mutationFn: (workspaces: Workspace[]) => {
|
||||
mutationFn: (workspaces: readonly Workspace[]) => {
|
||||
return Promise.all(workspaces.map((w) => stopWorkspace(w.id)));
|
||||
},
|
||||
onSuccess,
|
||||
|
@ -42,7 +42,7 @@ export function useBatchActions(options: UseBatchActionsProps) {
|
|||
});
|
||||
|
||||
const deleteAllMutation = useMutation({
|
||||
mutationFn: (workspaces: Workspace[]) => {
|
||||
mutationFn: (workspaces: readonly Workspace[]) => {
|
||||
return Promise.all(workspaces.map((w) => deleteWorkspace(w.id)));
|
||||
},
|
||||
onSuccess,
|
||||
|
@ -52,7 +52,7 @@ export function useBatchActions(options: UseBatchActionsProps) {
|
|||
});
|
||||
|
||||
const updateAllMutation = useMutation({
|
||||
mutationFn: (workspaces: Workspace[]) => {
|
||||
mutationFn: (workspaces: readonly Workspace[]) => {
|
||||
return Promise.all(
|
||||
workspaces
|
||||
.filter((w) => w.outdated && !w.dormant_at)
|
||||
|
@ -66,7 +66,7 @@ export function useBatchActions(options: UseBatchActionsProps) {
|
|||
});
|
||||
|
||||
const favoriteAllMutation = useMutation({
|
||||
mutationFn: (workspaces: Workspace[]) => {
|
||||
mutationFn: (workspaces: readonly Workspace[]) => {
|
||||
return Promise.all(
|
||||
workspaces
|
||||
.filter((w) => !w.favorite)
|
||||
|
@ -80,7 +80,7 @@ export function useBatchActions(options: UseBatchActionsProps) {
|
|||
});
|
||||
|
||||
const unfavoriteAllMutation = useMutation({
|
||||
mutationFn: (workspaces: Workspace[]) => {
|
||||
mutationFn: (workspaces: readonly Workspace[]) => {
|
||||
return Promise.all(
|
||||
workspaces
|
||||
.filter((w) => w.favorite)
|
||||
|
|
Loading…
Reference in New Issue