Skip to content
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

Collaborate on "newer" version, though slightly different direction? #88

Open
lars-erik opened this issue Sep 16, 2020 · 14 comments
Open

Comments

@lars-erik
Copy link

Hi ya'll!

I work for a diamond HubSpot partner in Norway. Of course we have our own .NET client as I'm sure a lot others have built over the last five years. Happy to see there is a community based open source initiative for this. On a sidenote, there's a .NET Core client in the works in another repo: https://github.com/skarpdev/dotnetcore-hubspot-client.

Fairly recently I submitted an idea to HubSpot to try to get them to publish an OpenAPI spec. of their v3 API at least. This is under review and hopefully likely to happen: https://community.hubspot.com/t5/HubSpot-Ideas/Publish-OpenAPI-specifications-for-the-APIs/idi-p/306942

With a full OpenAPI spec. we'll be able to use tools like NSwag to generate clients. Personally I prefer mirroring a kind of request / response structure, though with strictly typed classes. The properties collections would have to be dictionaries of course. But this is easy to build a mapper for afterwards.
I've currently started a temporary OpenAPI spec while waiting for an official one, and have a fairly nice client for the general list / get scenarios. It can easily be tested both integrated and stubbed using ApprovalTests.

My big question is: would you be interested in collaborating in a direction where OpenAPI is the "baseline"?
On a sidenote, I also have a powershell toolset based on the client which hopefully would be kind of similar to generate with a good base.

Hope this is interesting.
In any case, I'm working on something like this and if you want, I'd gladly cooperate rather than publishing a "competing" package. Not that competition isn't fruitful, but still. 🙂

Lars-Erik

@Psypher9
Copy link
Member

@lars-erik I think this sounds great! However, we have been trying to support the full specification of HubSpot's API's just have not had the manpower to fully close the gap quite yet.

I think meeting an OpenAPI spec is great, granted that we have one.

Have you taken a look at what we are currently doing? We are focused on making this project strongly-typed (you may have seen an earlier version which was based solely on dynamic types).

We have been trying to abstract away the request/response piece and allow developers consuming this project to use it like an SDK.

What are your thoughts on that?

@lars-erik
Copy link
Author

I think this sounds great! However, we have been trying to support the full specification of HubSpot's API's just have not had the manpower to fully close the gap quite yet.

🙌
I totally get the manpower thing. We've got V1 and V2 API wrappers that we built over 5-6 years.

I think meeting an OpenAPI spec is great, granted that we have one.

As mentioned, it's coming. I've got a simple one for now against the V3 API, and it only supports list / get for the main entities.
Should be quite easy to add the rest for CRUD. But then there's the transition from V2 to V3 that isn't done, and I suspect that's why we're still waiting for an official OpenAPI spec.

Have you taken a look at what we are currently doing? We are focused on making this project strongly-typed (you may have seen an earlier version which was based solely on dynamic types).

I have. My biggest turn off is RestSharp. Not that I got anything against it, but I don't see the benefit over pure HttpClient usage.
Regarding strongly typed entities, I don't think there should be an endeavor to transform properties into strongly typed properties. Properties are different in all portals, and the one's we want vary for pretty much every use case.

That being said, I wouldn't mind having a simple mapping library available. For instance like so:

var contact = contactClient.GetByEmail("[email protected]");
var typedContact = contact.As<SomeUseCaseDto>();

Whether the properties to load should be a params array or you then would use a parameter object is a very good question. I favor the latter, but defo. see the beauty of passing parameters for such a "small" API call. I believe NSwag let's us choose between both. I guess the biggest thing to agree on is how the generated clients should look. Maybe one for each style? Extensions?

We have been trying to abstract away the request/response piece and allow developers consuming this project to use it like an SDK.

I don't see a mismatch between Request / Response and SDKs. 😉
Not HttpRequestMessage and HttpResponseMessage of course.
I pretty much just mean parameter classes and result classes. IE. no long argument lists.

I just publicized the small V3 prototype I did with OpenAPI / NSwag.
Here's the OpenAPI spec so far:
https://github.com/lars-erik/markedspartner.hubspot.net/blob/main/openapi/HubSpotV3.yml
An example generated response class:
https://github.com/lars-erik/markedspartner.hubspot.net/blob/64d9a2ba42ec9dcca46c373e068b06990f3e8047/src/MarkedsPartner.HubSpot.Net/HubSpotV3.g.cs#L345
And example unit-test:
https://github.com/lars-erik/markedspartner.hubspot.net/blob/main/src/MarkedsPartner.HubSpot.Net.Tests/When_Getting_Companies.cs

In order to get "good integration tests", I think it'd be nice to have a onetime setup that seeds a developer portal and then runs against equally generated data each time. I don't see any reason for doing mock testing here, but possibly using a stubbed HttpClientManager.

Again, the repo linked is a totally new prototype for the V3 API. I think we'll keep our V1/V2 stuff neatly tucked away in our internal SCM. 😉

Hope this makes sense, and would really love to have a joint effort for HS APIs on the .NET platform.

@Psypher9
Copy link
Member

Psypher9 commented Oct 2, 2020

I have. My biggest turn off is RestSharp. Not that I got anything against it, but I don't see the benefit over pure HttpClient usage.

Yeah I get that. I'm not necessarily tied to this. I see the benefit for using HttpClient, especially with platforms like Blazor on the scene now. When @rezalas and I rewrote most of this project a couple years ago it just seemed like the best option at the time.

I actually just created #89 for just this reason.

I don't think there should be an endeavor to transform properties into strongly typed properties.

Right, we don't want to support that type of use case either. We really just support the generic shape of custom properties from the API. See ContactProperty for more information. Yeah I don't think it should be our responsibility to handle typing the value of these properties to a custom class the consumer will make.

But a mapper could be interesting. If you feel interested enough in that, go ahead and log an issue for it!

If you're up for working with us, we'd be glad to have you along!

@lars-erik
Copy link
Author

Sounds like we're quite aligned. :)

I'll keep hacking at the OpenAPI stuff for a while until it stabilizes. Maybe see about aligning APIs and methods when HubSpot launches an official spec? At least if it happens H1 2021. 😜
I guess if you'd go in that direction it would be an orphan branch?

@jamiehowarth0
Copy link

I've just been converting a Zendesk Sell API library to use strong types with RestSharp. It's .NET Standard but I'm also a Hubspot user and I'd like to help contribute too.

@Psypher9
Copy link
Member

Psypher9 commented Feb 5, 2021

@lars-erik @jamiehowarth0 let's do it!

@lars-erik
Copy link
Author

@ma3yta
Copy link

ma3yta commented Mar 13, 2021

https://developers.hubspot.com/changelog/get-all-publicly-available-open-api-specifications
https://api.hubspot.com/api-catalog-public/v1/apis/crm/v3/objects
https://api.hubspot.com/api-catalog-public/v1/apis/crm/v3/objects/contacts

code generation using NSwag produces invalid code RicoSuter/NSwag#3363 RicoSuter/NSwag#3362
OpenAPI Generator (https://github.com/OpenAPITools/openapi-generator) works fine

npm install @openapitools/openapi-generator-cli -g
openapi-generator-cli generate -i openapi.json -g csharp-netcore -o ApiClient --additional-properties packageName=HubSpot

@Psypher9
Copy link
Member

@ma3yta thanks for the update! @lars-erik it looks like we've got the Open API specs now!

@lars-erik
Copy link
Author

@Psypher9 We do. 🎉
Sorry, I've been way to busy. I have a node script that downloads them and makes them into Logic App connectors. That's the only I've got to play with it.

Looks like @ma3yta's suggestion about open api tools is a good one. I didn't have the best xp. with NSwag.

@lars-erik
Copy link
Author

Hi all,

I've gotten a bit further with this.
I now have a node pipeline that is in the last lap.
https://github.com/lars-erik/markedspartner.hubspot.net/tree/v2/main

I've got a "CLI" that downloads specified endpoints. For now I pipe one to file.
Wee removal of array, then it can be ran through the npm version of openapi-generator-cli.
I found that there's a tool called openapi-merge that I want to see if manages to "merge" all the APIs you want to use into one.
Running that output through openapi-generator should generate one solution for that set of APIs.

So fairly close. :)
Feel free to beat me to it with the code in the repo.
I'm off to the beach with the family. 🏖🌞🍻

@lars-erik
Copy link
Author

There! 🥳

I can now type

node index.js csharp CRM.Contacts,CRM.Companies

in the repo above, get a merged API spec from openapi-merge and then an openapi-generator generated C# (4.5.2) solution spat out based on the openapitools.json configuration file. It can be set up to "spit out" individual clients for all the .NET versions.

image

I'm not overly satisfied with the method names, but if nothing better, openapi-generator can be "templated" in order to change how the C# naming is done. Not sure if we could provoke the "Api classes", which seem to be based off tags.

In any case, I'm super happy to have something to automate the entire process.

Hope to hear your thoughts, and possibly even some teamwork to see about making something "proper and automated" from this.

(Oh, BTW, unless the entire template is modified, it seems RestSharp is there to stay. 😇)

@lars-erik
Copy link
Author

I've bugfixed and polished a bit, and the tool can now generate a full solution of all the APIs from one merged spec.
There's a couple of exceptions, and a couple of hoops to jump through, but it works.
Any language / framework can be generated based on the openapi-convert config file.

The only thing left for this to actually be kind of good is to find a fix for the operationIds. I've posted some feedback on the developer announcement thread. Will wait for feedback there before doing anything else.

https://community.hubspot.com/t5/Developer-Announcements/Announcing-a-new-endpoint-that-returns-all-publicly-available/m-p/458092/highlight/true#M124

Let me know your thoughts.
(I gather everyone is enjoying summer. 😎)

@jamiehowarth0
Copy link

I'm slightly miffed that the ecommerce API isn't yet there, but very happy that the OpenAPI specs are now freely available!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants