-
Notifications
You must be signed in to change notification settings - Fork 88
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Update Entity Type endpoints to return Subgraph #1220
Conversation
|
||
// ------------------- Type Guards to use inside .filters ------------------- | ||
|
||
export const isDataTypeVertex = (vertex: Vertex): vertex is DataTypeVertex => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These are necessary because Typescript doesn't seem to understand that vertex.kind === "dataType"
constrains the type if you continue past a filter
(for example with a map
)
@@ -0,0 +1,231 @@ | |||
import { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc: @yusufkinatas @nathggns @luisbettencourt @CiaranMn
As the Subgraph becomes more prevalent in the frontend code, I suspect we'll want more helper methods to interact with it. I have created this file to hold them while we flesh such things out. Tagging you so you know they're here, hopefully it'll save you frustration
.find((item) => item.propertyTypeId.startsWith(propertyTypeId)) | ||
?.propertyType.title.toLowerCase(), | ||
})); | ||
const propertyTypes: { title?: string; propertyTypeBaseUri: string }[] = |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yusufkinatas just wanted to flag that this has been changed.
propertyTypeBaseUri, | ||
); | ||
|
||
/** @todo - pick the latest version? */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're going through the properties
of an entity here, so the keys are base URIs. That means that we could potentially have multiple versions of the type that matches.
I suspect the best thing to do would be to pick the latest, or to look at the entity's entity type and find the version of the property type used inside that.
@@ -61,6 +62,7 @@ interface PropertyTableProps { | |||
|
|||
type EnrichedPropertyType = PropertyType & { | |||
value: any; | |||
/** @todo - Correct this, it is a property type BaseUri not an ID (it's unversioned) */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yusufkinatas I didn't want to change too much in the PR but we should try and distinguish between baseUri
s and the ID
s of types (VersionedUri
s)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And to flag that the most recent commit moves these changes and TODO 9ffa4cd
@@ -69,15 +71,22 @@ const getDataTypesOfPropertyType = ( | |||
propertyType: PropertyType, | |||
entity: EntityResponse, | |||
) => { | |||
/** @todo check why propertyValue does not have with a proper type */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It did have the proper type, I'm not sure what this was about 😁
if (dataTypeVertex?.kind !== "dataType") { | ||
throw new Error( | ||
`Expected "dataType" vertex but got ${dataTypeVertex.kind}`, | ||
); | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not sure how we want to handle these sorts of things. I wrote this before I wrote the helper methods so we could use isDataType
here, but generally speaking I think we should trust that a datatype ID will go to a data type? And just use type assertions?
Not sure, maybe we'd prefer more safety, or maybe we'd prefer it to be a bit faster and avoid the checks.
cc: @CiaranMn if you have any thoughts
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I expect we would need to have millions of these checks before it made any discernible difference to performance.
We can remove them if something appears slow and it would make any difference.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Valid, but also a question of code ergonomics. Do we want to be writing the checks everywhere, or do we just want to write as DataTypeVertex
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not against asserting the type if we're 100% sure it logically must be what we are asserting it is, but I don't think we should do so because of performance worries in this instance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to be writing the checks everywhere, or do we just want to write as DataTypeVertex
Presumably there's only a limited number of ways in which we want to retrieve a thing from the subgraph and check it is what it's supposed to be, so we should have a limited number of functions that do that, and keep the checks inside them.
I don't feel strongly about this, if I saw this and it had an assertion with a comment explaining that it was definitely going to be the thing I wouldn't care. But we should comment any assertion.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to be adding a comment everywhere we do this:
hash/packages/hash/frontend/src/pages/[account-slug]/entities/[entity-id].page/types-section.tsx
Lines 43 to 47 in fb8ad44
const entityTypeTitle = ( | |
entity.entityTypeRootedSubgraph.vertices[ | |
entity.entityTypeId | |
]! as EntityTypeVertex | |
).inner.inner.title; |
Or do we want to just create methods for all of them:
getDataType(dataTypeId: VersionedUri, subgraph: Subgraph): PersistedDataType
getPropertyType(propertyTypeId: VersionedUri, subgraph: Subgraph): PersistedPropertyType
and so on
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would create methods for them. Again, I don't feel strongly about this, I'm offering an opinion because you've asked, feel free to think it's too cumbersome
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'll add the methods :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
val.propertyTypeId.startsWith(propertyTypeId), | ||
) ?? {}; | ||
return Object.keys(entity.properties).map((propertyTypeBaseUri) => { | ||
const propertyTypeVersions = getPropertyTypesByBaseUri( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've made a little helper method to encapsulate finding types by their Base URI. Importantly this returns a list now, not just using find
, because there could be multiple.
@@ -35,19 +35,23 @@ export const useEntityType = ( | |||
entityTypeRef.current = null; | |||
|
|||
void aggregateEntityTypes({ data: {} }).then(async (res) => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cc: @nathggns, just want to check you're happy with these specific changes
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I'm happy with this, thanks @Alfred-Mountfield
? propertyTypeIds.map((propertyTypeId) => { | ||
const vertex = entityTypeRootedSubgraph.vertices[propertyTypeId]; | ||
|
||
/** @todo - what to do here if the property type isn't in the subgraph, make another call? */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is a wider question I have and am unsure of. It maybe can be solved when we also allow the depths to be configured through the BP functions?
cc: @CiaranMn for thoughts on BP ergonomics
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I expect in practice that most people are going to interact with types via queries that resolve all property, data, and link types referred to by a type (including within property types etc). We should make that easy.
If they choose not to they can make another call to get missing things.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think for the entity type -> property type -> data type
tree, having max depth parameters (255) automatically populated is probably reasonable for most queries. I'm not sure about entity type -> entity type though. (Constraints on links for example), that could blow up the query very fast.
And it gets a lot less clear to me when we're dealing with knowledge graph stuff, not just ontology. For queries like getEntity
or aggregateEntities
do we really want to return the full entity type -> property type -> data type
tree?
It maybe can be solved when we also allow the depths to be configured through the BP functions?
Hence me thinking that. But it's probably good thinking about the patterns whereby we're going to need to make additional lookups (or account for it). Do we want to just assume that the full thing will fit in 255 (pretty safe bet for types in my eyes) and fatally error if it's not there? Or do we want to have fallback logic for follow-up queries on every single element kind, any time we look for something in the subgraph.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we want to just assume that the full thing will fit in 255 (pretty safe bet for types in my eyes) and fatally error if it's not there?
I think that's fine for types.
Or do we want to have fallback logic for follow-up queries on every single element kind, any time we look for something in the subgraph.
For some uses we will want that. I don't think it will come up in this particular one. We should not pollute the 'get thing from subgraph' function with follow-up query logic though. There could be some other function that does that and calls the 'get thing from subgraph'to check first, and then gets it from the API as needed, but I wouldn't worry about that until we need it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should not pollute the 'get thing from subgraph' function with follow-up query logic though
100% on the same page there, otherwise you'd have to pass in all the hooks, it'd be a massive pain.
We can leave it as is then, I just have a mild concern we won't think about the edge-cases where we will want that until we discover a bug in prod
9b9bff2
to
66cc9af
Compare
...lug]/entities/[entity-id].page/property-table/extract-enriched-property-types-from-entity.ts
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks Alfie! It is looking good so far. Have some things we should look at, though
(thought this was submitted as a review, but I had added single comments. My bad.)
This pull request introduces 3 alerts and fixes 2 when merging 20e9512 into 244d2b6 - view on LGTM.com new alerts:
fixed alerts:
|
const [propertyTypes, setPropertyTypes] = | ||
useState<PropertyTypesContextValues | null>(null); | ||
const { aggregatePropertyTypes } = useBlockProtocolAggregatePropertyTypes(); | ||
|
||
useEffect(() => { | ||
void aggregatePropertyTypes({ data: {} }).then(({ data }) => { | ||
if (typeSystemLoading) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nathggns I've had to add this check, is that alright?
I thought we were going to wrap all of the pages in these but it seems we're calling them in individual places?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we're doing this on an individual page level still – but i've changed this in a follow up PR to share the status by context. This seems a sensible change
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks! We got the last issues ironed out and it looks good to me. Tested various pages locally
This pull request fixes 2 alerts when merging d52565a into 244d2b6 - view on LGTM.com fixed alerts:
|
🌟 What is the purpose of this PR?
This follows on from #1198. It modifies property type methods front to back to use the
Subgraph
type.It fixes a bug with the GraphQL definitions to correctly allow the depths to be configured, and updates the hooks to use the new definitions.
It introduces a suite of helper methods for the
Subgraph
object to be used in the frontend (for now, these should probably be moved elsewhere when they are more mature)It also updates frontend code to use the new helper methods and deal with the new return types. Relevant people have been tagged
🔗 Related links
🔍 What does this change?
Commits should be very nice and clean, please consult them.
📜 Does this require a change to the docs?
It probably will, this will happen as a follow-up (tracked in this asana task (internal))
Entity
havingEntityTypeRootedSubgraph
on it which is actually aSubgraph
object)Persisted*
types which can be imported from various GraphQL definitions, thehash-graph-client
package, or from the actual original source of the scalars that go into GraphQL. I'm not entirely sure how to solve this right now. I think the proper solution is establishing a clear boundary of what does and doesn't reach the frontend through the BP, and then defining those types universally through the type system package.🐾 Next steps
LinkType
endpoints to useSubgraph
Link
endpoints to useSubgraph
Entity
endpoints to useSubgraph
🛡 What tests cover this?
This was a full stack change, so all the tests of HASH should be checked. These include the ones outlined in the Graph README, as well as workspace integration tests, and manual testing of the application.
❓ How to test this?
yarn external-services up --build
andyarn dev
type-editor
routeScreen.Recording.2022-10-19.at.17.26.18.mov