<button hx-get="/contact/1/edit">
And here's the datastar one, edited for parity: [1]
<button data-on:click="@get('/contact/1/edit')">
The htmx one is simpler. There's fewer mini-languages to learn and the API makes more assumptions about what you want. As you noted, Datastar has more generalized mechanisms that are certainly less clunky than htmx's if you lean heavily into more signals- or event-driven behavior, but for (what I believe to be) the majority use-case of a CRUD website, htmx's simpler interface is easier to implement and debug.(For example: you will see the response associated with the request in the browser network tab; I'm not sure if Datastar has a non-SSE mode to support that but it wouldn't be true for SSE.) To each their own.
As for "well then why implement X, Y, or Z," as the OP notes, refactoring to use fetch() means you get them largely for free, without compromising the nice interface. So why not?