HubSpot.NET icon indicating copy to clipboard operation
HubSpot.NET copied to clipboard

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

Open lars-erik opened this issue 4 years ago • 14 comments

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

lars-erik avatar Sep 16 '20 13:09 lars-erik

@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?

Psypher9 avatar Sep 29 '20 19:09 Psypher9

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.

lars-erik avatar Sep 30 '20 12:09 lars-erik

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!

Psypher9 avatar Oct 02 '20 06:10 Psypher9

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?

lars-erik avatar Oct 02 '20 09:10 lars-erik

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.

jamiehowarth0 avatar Jan 11 '21 21:01 jamiehowarth0

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

Psypher9 avatar Feb 05 '21 14:02 Psypher9

@Psypher9 If only there were news. :)
https://community.hubspot.com/t5/HubSpot-Ideas/Publish-OpenAPI-specifications-for-the-APIs/idi-p/306942

lars-erik avatar Feb 05 '21 15:02 lars-erik

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 https://github.com/RicoSuter/NSwag/issues/3363 https://github.com/RicoSuter/NSwag/issues/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

ma3yta avatar Mar 13 '21 06:03 ma3yta

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

Psypher9 avatar Apr 27 '21 18:04 Psypher9

@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 avatar Apr 27 '21 19:04 lars-erik

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 avatar Jul 09 '21 11:07 lars-erik

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 avatar Jul 12 '21 14:07 lars-erik

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. 😎)

lars-erik avatar Jul 13 '21 11:07 lars-erik

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

jamiehowarth0 avatar Jul 23 '21 10:07 jamiehowarth0