Skip to content
This repository was archived by the owner on Feb 8, 2024. It is now read-only.

Connect: Use typed URIs#1394

Merged
ravicious merged 8 commits intomasterfrom
ravicious/typed-uris
Dec 14, 2022
Merged

Connect: Use typed URIs#1394
ravicious merged 8 commits intomasterfrom
ravicious/typed-uris

Conversation

@ravicious
Copy link
Copy Markdown
Member

No description provided.

@ravicious
Copy link
Copy Markdown
Member Author

@avatus @gzdunek This is what I cooked up. There's 35 remaining type errors in 19 files but I'll leave that for later. Submitting this as a WIP because I don't have more time for this today.

In a sound type system, we'd have to validate incoming values to ensure they actually match the type. That is, when making an RPC and getting some objects, we'd have to make a runtime check to verify that the URI indeed matches the type.

In TypeScript, we can cheat a little and just say that we trust that anything that comes from tshd is the type it purports to be.


I have to say this is pretty nice. I already made a couple of mistakes while fixing the types in tests and TypeScript immediately caught those.

I'm unsure if there are any unforeseen roadblocks ahead, but I think if we ensure any incoming objects are properly typed (for now it's just stuff from tshd) and that docs & gateways are created with correct types, I think there's nothing which would prevent us from using this approach.

Comment thread packages/teleterm/src/ui/uri.ts Outdated
Comment on lines +39 to +40
export type RootClusterServerUri =
`/clusters/${RootClusterId}/servers/${ServerId}`;
Copy link
Copy Markdown
Member Author

@ravicious ravicious Nov 30, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great if we could restrict RootClusterId to a stricter type then string.

Currently, this is valid code because foo/leaves/bar is a string so it's a valid value for RootClusterId.

const uri1: RootClusterServerUri = '/clusters/foo/leaves/bar/servers/quux'
const uri2: RootClusterUri = '/clusters/foo/leaves/bar/servers/quux'
const uri3: RootClusterUri = '/clusters/foo/leaves/bar'

If it's not possible, then perhaps we shouldn't define types which cannot be enforced and instead focus just on those that we actually can. So we'd be able to differentiate a document URI from a resource URI, server URI from database URI. But we wouldn't be able to differentiate a root cluster URI from a leaf cluster URI.

This would still provide some value.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mean, technically the current implementation would at least prohibit us from passing a root cluster URI where a leaf cluster URI is expected. But I don't think this is that useful, we don't have many places where leaf cluster URIs are allowed but root cluster URIs are prohibited. And it doesn't outweigh the false positive of passing leaf cluster URI as a root cluster URI.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be great if we could restrict RootClusterId to a stricter type then string.

AFAIK it is not possible, hopefully in the future we will be able to create regex-validated string types.

If it's not possible, then perhaps we shouldn't define types which cannot be enforced and instead focus just on those that we actually can.

Hmm, I would define them anyway. They would act as type aliases. I think it is still better for the reader to see clusterUri: RootClusterUri than clusterUri: string. You could also add a short comment to the type definition with an example.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think our types need to differentiate between root/leaf (i mean... if it was an easy fix sure), but as you said, there is nowhere that expects leaf only, just places that require root only.

I agree that defining them anyway would help future readers. not only would we have params named stuff like rootClusterUri but also typed for double safety.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is still better for the reader to see clusterUri: RootClusterUri than clusterUri: string.

Ah, those would still be typed, we wouldn't use string. It's just that because we cannot differentiate between root and leaf URIs, we'd have a single ClusterUri type that accepts both. So instead of clusterUri: RootClusterUri you'd have rootClusterUri: ClusterUri. And as Michael said, I think in those cases the name of the variable should be rootClusterUri no matter what the type is. ;)


However, we could make the same argument about cluster URIs vs resource URIs. This code works:

const serverUri: RootClusterServerUri = '/clusters/foo/servers/bar'
const uri: RootClusterUri = serverUri
const leafServerUri: LeafClusterServerUri = '/clusters/foo/leaves/baz/servers/bar'
const leafUri: LeafClusterUri = leafServerUri

But I wouldn't want to remove the distinction between clusters and resources in types simply because we can't prevent resource URIs being passed as cluster URIs.

So yeah, maybe let's keep it as it is for now and see how it works out. Refactoring this will be super easy anyway.

@ravicious ravicious force-pushed the ravicious/typed-uris branch from 1c81388 to 9125457 Compare December 2, 2022 17:04
Copy link
Copy Markdown
Member Author

@ravicious ravicious left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to take another look at this PR on Monday.

I tried to change just types where possible, I didn't even touch arg names just to reduce the possible bug surface here.

options.kubeConfigRelativePath ||
// We prepend the name with `rootClusterId/` to create a kube config
// inside this directory. When the user logs out of the cluster,
// the entire directory is deleted.
Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved this comment around because it was messing up syntax highlighting in my editor. ;f

@ravicious ravicious marked this pull request as ready for review December 2, 2022 17:07
@ravicious ravicious requested review from avatus and gzdunek December 2, 2022 17:08
@ravicious
Copy link
Copy Markdown
Member Author

@avatus @gzdunek Anything I can do to make this easier to review? The longer it sits here, the harder it'll be to resolve the conflicts.

Copy link
Copy Markdown
Contributor

@gzdunek gzdunek left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

Comment thread packages/teleterm/src/ui/TopBar/Clusters/Clusters.tsx Outdated
Copy link
Copy Markdown
Contributor

@avatus avatus left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one left my mind. Sorry about missing it. LGTM

@ravicious ravicious force-pushed the ravicious/typed-uris branch from 9125457 to ff0a751 Compare December 14, 2022 16:02
@ravicious ravicious merged commit c685432 into master Dec 14, 2022
@ravicious ravicious deleted the ravicious/typed-uris branch December 14, 2022 16:20
@ravicious
Copy link
Copy Markdown
Member Author

Merged. Let me know if you encounter any issues in your open PRs.

ravicious added a commit that referenced this pull request Dec 14, 2022
* Remove ClustersService methods related to apps

I had problems with the new types and apps because I didn't create a
separate type for app URI. So I decided to remove it all because it isn't
used anyway.

* Remove WorkspacesService.getWorkspacesDocumentsServices

This method wasn't used anywhere since #1203 got merged.
ravicious added a commit that referenced this pull request Dec 14, 2022
* Remove ClustersService methods related to apps

I had problems with the new types and apps because I didn't create a
separate type for app URI. So I decided to remove it all because it isn't
used anyway.

* Remove WorkspacesService.getWorkspacesDocumentsServices

This method wasn't used anywhere since #1203 got merged.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants