@niroai/niro 0.17.0 → 0.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (177) hide show
  1. package/CHANGELOG.md +136 -0
  2. package/README.md +123 -302
  3. package/bin/niro.js +12 -1
  4. package/docs/agent-antigravity.md +37 -0
  5. package/docs/agent-claude-code.md +48 -0
  6. package/docs/agent-claude-desktop.md +47 -0
  7. package/docs/agent-cline.md +42 -0
  8. package/docs/agent-codex.md +45 -0
  9. package/docs/agent-copilot-cli.md +42 -0
  10. package/docs/agent-cursor.md +44 -0
  11. package/docs/agent-factory.md +42 -0
  12. package/docs/agent-gemini-cli.md +42 -0
  13. package/docs/agent-goose.md +42 -0
  14. package/docs/agent-kiro.md +37 -0
  15. package/docs/agent-opencode.md +37 -0
  16. package/docs/agent-vscode.md +45 -0
  17. package/docs/agent-windsurf.md +38 -0
  18. package/docs/answer-shapes.md +69 -0
  19. package/docs/builds-and-updates.md +68 -0
  20. package/docs/cloud-README.md +372 -0
  21. package/docs/configuring-a-folder.md +51 -0
  22. package/docs/connect-ci.md +24 -0
  23. package/docs/connect-overview.md +20 -0
  24. package/docs/connect-review-bots.md +17 -0
  25. package/docs/connect-team-server.md +12 -0
  26. package/docs/connect-terminal.md +49 -0
  27. package/docs/connect-web-agents.md +9 -0
  28. package/docs/connect-your-ai-assistant.md +59 -175
  29. package/docs/coverage-audit-and-consent.md +51 -0
  30. package/docs/evaluate-what-niro-did.md +271 -0
  31. package/docs/faq-assistants-and-mcp.md +122 -0
  32. package/docs/faq-feedback-and-receipts.md +33 -0
  33. package/docs/faq-indexing.md +127 -0
  34. package/docs/faq-install-and-setup.md +103 -0
  35. package/docs/faq-licence-and-plans.md +86 -0
  36. package/docs/faq-login-and-account.md +69 -0
  37. package/docs/faq-offline.md +34 -0
  38. package/docs/faq-performance.md +33 -0
  39. package/docs/faq-privacy-and-security.md +113 -0
  40. package/docs/faq-uninstall.md +47 -0
  41. package/docs/faq-updates.md +59 -0
  42. package/docs/faq-worktrees-and-branches.md +59 -0
  43. package/docs/faq-wrong-or-missing-answers.md +275 -0
  44. package/docs/hosted-only.md +33 -0
  45. package/docs/how-the-graph-works.md +47 -0
  46. package/docs/index.md +157 -0
  47. package/docs/licence-and-plans.md +72 -0
  48. package/docs/lifecycle-debug.md +48 -0
  49. package/docs/lifecycle-onboarding.md +32 -0
  50. package/docs/lifecycle-overview.md +77 -0
  51. package/docs/lifecycle-plan-and-design.md +44 -0
  52. package/docs/lifecycle-review.md +30 -0
  53. package/docs/lifecycle-security-and-privacy.md +35 -0
  54. package/docs/lifecycle-test.md +28 -0
  55. package/docs/lifecycle-write-code.md +35 -0
  56. package/docs/llms-full.txt +8015 -0
  57. package/docs/llms.txt +126 -0
  58. package/docs/playbook-add-a-feature.md +108 -0
  59. package/docs/playbook-change-safely.md +93 -0
  60. package/docs/playbook-data-and-events.md +107 -0
  61. package/docs/playbook-debug-after-a-change.md +96 -0
  62. package/docs/playbook-debug-config.md +95 -0
  63. package/docs/playbook-debug-exception.md +124 -0
  64. package/docs/playbook-debug-failing-service-call.md +119 -0
  65. package/docs/playbook-debug-slow-path.md +80 -0
  66. package/docs/playbook-debug-wrong-value.md +137 -0
  67. package/docs/playbook-onboard.md +95 -0
  68. package/docs/playbook-review-a-change.md +72 -0
  69. package/docs/playbook-test-a-change.md +73 -0
  70. package/docs/reference-cli.md +113 -0
  71. package/docs/reference-config-files.md +42 -0
  72. package/docs/reference-engine-commands.md +56 -0
  73. package/docs/reference-environment-variables.md +89 -0
  74. package/docs/reference-exit-codes.md +67 -0
  75. package/docs/reference-limits.md +75 -0
  76. package/docs/reference-mcp-tools.md +326 -0
  77. package/docs/reference-messages.md +180 -0
  78. package/docs/secrets-and-masking.md +48 -0
  79. package/docs/supported-c.md +130 -0
  80. package/docs/supported-cpp.md +157 -0
  81. package/docs/supported-csharp.md +211 -0
  82. package/docs/supported-go.md +258 -0
  83. package/docs/supported-java.md +226 -0
  84. package/docs/supported-javascript.md +223 -0
  85. package/docs/supported-kotlin.md +124 -0
  86. package/docs/supported-overview.md +89 -0
  87. package/docs/supported-php.md +157 -0
  88. package/docs/supported-python.md +224 -0
  89. package/docs/supported-ruby.md +162 -0
  90. package/docs/supported-rust.md +150 -0
  91. package/docs/supported-swift.md +133 -0
  92. package/docs/supported-typescript.md +220 -0
  93. package/docs/tokens-speed-and-accuracy.md +99 -0
  94. package/docs/troubleshooting.md +42 -0
  95. package/docs/uninstall.md +74 -0
  96. package/docs/what-leaves-your-machine.md +71 -0
  97. package/docs/where-things-are-stored.md +59 -0
  98. package/docs/worktrees-and-branches.md +55 -0
  99. package/package.json +5 -3
  100. package/src/commands/add-repo.js +5 -0
  101. package/src/commands/auditSend.js +67 -0
  102. package/src/commands/build.js +6 -0
  103. package/src/commands/docsSend.js +73 -0
  104. package/src/commands/engine.js +120 -0
  105. package/src/commands/engineRoutes.js +105 -0
  106. package/src/commands/guide.js +254 -0
  107. package/src/commands/init.js +6 -2
  108. package/src/commands/initLocal.js +96 -0
  109. package/src/commands/journalSend.js +47 -0
  110. package/src/commands/login.js +89 -12
  111. package/src/commands/mcp.js +22 -6
  112. package/src/commands/plan.js +99 -0
  113. package/src/commands/repoPush.js +33 -0
  114. package/src/commands/requestIntegration.js +38 -0
  115. package/src/commands/share.js +56 -0
  116. package/src/commands/start.js +451 -371
  117. package/src/commands/status.js +57 -0
  118. package/src/commands/takeover.js +6 -0
  119. package/src/commands/uninstall.js +180 -0
  120. package/src/commands/upgrade.js +38 -8
  121. package/src/commands/watch.js +420 -6
  122. package/src/index.js +174 -3
  123. package/src/lib/agentApi.js +32 -1
  124. package/src/lib/api.js +20 -6
  125. package/src/lib/auditUpload.js +293 -0
  126. package/src/lib/branchDrift.js +149 -0
  127. package/src/lib/choose.js +116 -0
  128. package/src/lib/cloudGuard.js +74 -0
  129. package/src/lib/credentials.js +2 -2
  130. package/src/lib/docsMarked.js +55 -0
  131. package/src/lib/docsState.js +213 -0
  132. package/src/lib/docsUpload.js +481 -0
  133. package/src/lib/engine.js +619 -0
  134. package/src/lib/folderSync.js +2 -1
  135. package/src/lib/graphCheck.js +40 -0
  136. package/src/lib/guide.js +293 -0
  137. package/src/lib/guideSearch.js +252 -0
  138. package/src/lib/integrationRequest.js +89 -0
  139. package/src/lib/journalUpload.js +147 -0
  140. package/src/lib/languages.js +129 -0
  141. package/src/lib/lease.js +375 -0
  142. package/src/lib/localBuild.js +285 -0
  143. package/src/lib/localEngine.js +210 -0
  144. package/src/lib/localOnboard.js +124 -0
  145. package/src/lib/localWorktrees.js +243 -0
  146. package/src/lib/machineCheck.js +58 -0
  147. package/src/lib/mcpClients.js +10 -1
  148. package/src/lib/migrationNotice.js +118 -0
  149. package/src/lib/modelFetch.js +153 -0
  150. package/src/lib/nestedOutput.js +23 -9
  151. package/src/lib/onboardingLog.js +34 -0
  152. package/src/lib/planUsage.js +165 -0
  153. package/src/lib/progressBar.js +46 -0
  154. package/src/lib/prompt.js +1 -1
  155. package/src/lib/redact.js +155 -0
  156. package/src/lib/release.js +33 -0
  157. package/src/lib/repoPush.js +495 -0
  158. package/src/lib/secret.js +1 -1
  159. package/src/lib/service.js +372 -63
  160. package/src/lib/shareCode.js +367 -0
  161. package/src/lib/shareExclusions.js +114 -0
  162. package/src/lib/shareFiles.js +129 -0
  163. package/src/lib/spinner.js +9 -5
  164. package/src/lib/watchDaemon.js +33 -10
  165. package/src/lib/watchState.js +12 -1
  166. package/src/lib/windowsPaths.js +67 -0
  167. package/src/mcp/lineCheck.js +382 -0
  168. package/src/mcp/lineName.js +92 -0
  169. package/src/mcp/localBackend.js +751 -0
  170. package/src/mcp/localMode.js +383 -0
  171. package/src/mcp/localSkill.js +189 -0
  172. package/src/mcp/server.js +610 -79
  173. package/src/mcp/setup.js +519 -131
  174. package/src/mcp/shellSearchHook.js +509 -0
  175. package/src/mcp/teardown.js +173 -91
  176. package/src/mcp/usingNiro.js +39 -0
  177. package/docs/working-on-branches.md +0 -162
@@ -0,0 +1,258 @@
1
+ # Supported in Go
2
+
3
+ <!-- GENERATED by scripts/gen-supported-docs.js. Do not edit by hand: run the script again. -->
4
+ <!-- source: catalog/go.json; catalog/go.structure.json -->
5
+ <!-- measured: coverage corpus 1bb4ebb, niro-local 2b30d4fd -->
6
+
7
+ This page lists the Go libraries, frameworks and build tools Niro was tested against, and whether it recognised each one.
8
+
9
+ **What the marks mean.**
10
+
11
+ - **Supported:** Niro recognised every way of using it that the test code tries.
12
+ - **Partly:** Niro recognised some of those ways, or recognised one only in part.
13
+ - **Not yet:** Niro did not recognise it in the test code.
14
+
15
+ The test code is made up for the purpose: one small service per library, with the names invented. So "supported" means Niro recognised it there. It is good evidence, but it is not a promise about every codebase. If Niro misses something in your code, the coverage audit reports the gap on its own (see [coverage-audit-and-consent.md](coverage-audit-and-consent.md)).
16
+ <!-- source: niro-coverage-corpus README.md ("Synthetic test code ... All names are made up"); catalog status merged pairs one to one with measured found -->
17
+
18
+ The test catalog also holds 9 look-alike cases for Go: code that Niro must NOT take for a route, a call or a store. They test that Niro ignores the look-alike, so they are left out of this page and its counts.
19
+ <!-- source: catalog/go.json and catalog/go.structure.json, rows marked as traps (scripts/gen-supported-docs.js isTrap) -->
20
+
21
+ ## Web frameworks and HTTP servers (the routes your code serves)
22
+
23
+ 19 supported, 0 partly, 9 not yet.
24
+
25
+ | Name | Status | Ways of using it that were tested |
26
+ |---|---|---|
27
+ | AWS SAM template.yaml | supported | yes: AWS::Serverless::Function (Runtime provided.al2023, Handler bootstrap, Metadata BuildMethod go1.x) with Events Type HttpApi Path and Method; the handler is the package main under CodeUri |
28
+ | encore.dev | not yet | no: //encore:api comment directive above a function |
29
+ | github.com/beego/beego/v2 | supported | yes: web.Router with a controller and 'verb:Method' mapping<br>yes: web.Get functional route with a literal<br>yes: NewNamespace with NSRouter |
30
+ | github.com/cloudwego/hertz | supported | yes: verbs on server.Default() held in `h`<br>yes: Group then verb |
31
+ | github.com/danielgtaylor/huma/v2 | supported | yes: huma.Get(api, path, handler) package helper<br>yes: huma.Register with an Operation literal naming Method and Path |
32
+ | github.com/dapr/go-sdk | not yet | no: service AddServiceInvocationHandler(path, h) |
33
+ | github.com/fasthttp/router | supported | yes: fasthttp/router verbs and Group |
34
+ | github.com/gin-gonic/gin | supported | yes: engine verb methods with a method-value handler<br>yes: inline function literal handler<br>yes: Handle with the verb as a string<br>yes: Any registers every verb<br>yes: route group with a block<br>yes: *gin.RouterGroup passed to a register function in another file |
35
+ | github.com/go-chi/chi/v5 | supported | yes: chi verb methods<br>yes: Route with a function literal, nested twice<br>yes: Method with a verb constant and an http.Handler<br>yes: inline middleware chain before the verb<br>yes: Mount a sub-router returned by a function |
36
+ | github.com/go-kit/kit (transport/http) | not yet | no: go-kit httptransport.NewServer mounted on a gorilla route |
37
+ | github.com/go-kratos/kratos (HTTP transport) | not yet | no: kratos generated *_http.pb.go registering routes |
38
+ | github.com/go-martini/martini | supported | yes: verbs on martini.Classic() held in `m`<br>yes: Group with a function literal |
39
+ | github.com/gobuffalo/buffalo | not yet | no: buffalo app verbs |
40
+ | github.com/gofiber/fiber/v2 | supported | yes: Fiber verb methods<br>yes: Add with a verb constant<br>yes: Group<br>yes: Route with a function literal |
41
+ | github.com/gofiber/fiber/v3 | not yet | no: fiber v3 verbs (handler takes fiber.Ctx interface) |
42
+ | github.com/gorilla/mux | supported | yes: HandleFunc(...).Methods(verb)<br>yes: Handle(path, http.HandlerFunc(m)).Methods(verb)<br>yes: chain starting with Methods, then Path, then HandlerFunc<br>yes: PathPrefix(...).Subrouter() |
43
+ | github.com/julienschmidt/httprouter | supported | yes: httprouter verb methods<br>yes: Handle with a verb constant<br>yes: HandlerFunc with a plain http.HandlerFunc |
44
+ | github.com/kataras/iris/v12 | supported | yes: iris verbs and Party<br>yes: Handle with a verb string |
45
+ | github.com/labstack/echo/v4 | supported | yes: Echo verb methods<br>yes: Add with a verb constant<br>yes: Match with a verb list<br>yes: Group with a prefix |
46
+ | github.com/oapi-codegen/oapi-codegen (generated server) | not yet | no: generated RegisterHandlers: router.GET(baseURL+path, wrapper.X) inside checked-in generated code |
47
+ | github.com/revel/revel | not yet | no: conf/routes file |
48
+ | github.com/uptrace/bunrouter | supported | yes: bunrouter verbs<br>yes: WithGroup with a function literal |
49
+ | github.com/zeromicro/go-zero | supported | yes: AddRoutes with a []rest.Route literal and rest.WithPrefix<br>yes: AddRoute with one rest.Route literal |
50
+ | goa.design/goa/v3 | not yet | no: goa design DSL plus generated server |
51
+ | gofr.dev | supported | yes: gofr app verbs |
52
+ | Netlify Functions (Go, Lambda compatibility) | supported | yes: netlify/functions/<name>/main.go (or <name>.go) with lambda.Start: served at /.netlify/functions/<name>, every verb; a -background suffix makes a background function<br>yes: netlify.toml [[redirects]] from a path to /.netlify/functions/<name> with status 200 gives the function that path too<br>yes: netlify.toml [functions] directory = "<folder>" moves where function folders are read from |
53
+ | Serverless Framework serverless.yml | supported | yes: functions.<name> with handler bootstrap and package.artifact, events httpApi; runtime provided.al2023 |
54
+ | Vercel Functions (Go runtime, /api directory) | supported | yes: api/<name>.go with an exported func(http.ResponseWriter, *http.Request): the file path is the route, every verb<br>yes: api/cards/[id].go: a bracketed file name is a dynamic path segment |
55
+
56
+ ## The language's own HTTP server
57
+
58
+ 0 supported, 2 partly, 0 not yet.
59
+
60
+ | Name | Status | Ways of using it that were tested |
61
+ |---|---|---|
62
+ | net/http | partly | yes: http.HandleFunc on the default mux, inline func literal handler<br>yes: http.Handle with a type implementing http.Handler (ServeHTTP)<br>yes: ServeMux.HandleFunc with Go 1.22 pattern 'METHOD /path/{wildcard}'<br>yes: ServeMux.Handle with a method pattern and an http.Handler value<br>yes: http.HandlerFunc(fn) adapter passed to Handle<br>yes: Go 1.22 trailing wildcard {name...}<br>yes: Go 1.22 exact-match marker {$}<br>yes: Go 1.22 host-qualified pattern<br>partly: pre-1.22 single path, verb chosen by switch r.Method in the handler<br>yes: second ServeMux mounted under a prefix with http.StripPrefix |
63
+ | net/rpc | partly | yes: rpc.Register + rpc.HandleHTTP: every exported method T.M(args, *reply) error is a procedure<br>yes: rpc.RegisterName with a custom service name<br>no: rpc.NewServer + jsonrpc.NewServerCodec over raw TCP |
64
+
65
+ ## HTTP client libraries (the calls your code makes to other services)
66
+
67
+ 2 supported, 5 partly, 8 not yet.
68
+
69
+ | Name | Status | Ways of using it that were tested |
70
+ |---|---|---|
71
+ | github.com/carlmjohnson/requests | supported | yes: requests.URL(base).Pathf().ToJSON().Fetch(ctx)<br>yes: BodyJSON().Post().Fetch |
72
+ | github.com/cloudwego/hertz (client) | partly | yes: hertz client.Get(ctx, dst, url)<br>no: protocol.Request SetMethod/SetRequestURI then client Do |
73
+ | github.com/dapr/go-sdk | not yet | no: client.InvokeMethod(ctx, appID, method, verb): service invocation by app name |
74
+ | github.com/dghubble/sling | not yet | no: sling.New().Base(url); New().Get(path).ReceiveSuccess<br>no: Post(path).BodyJSON().ReceiveSuccess |
75
+ | github.com/go-kit/kit (transport/http client) | not yet | no: httptransport.NewClient(verb, url, enc, dec) |
76
+ | github.com/go-resty/resty/v2 | partly | yes: client with SetBaseURL; R().SetPathParam().Get(path)<br>yes: R().SetBody().Post<br>yes: R().SetContext().SetBody().Put<br>no: R().Execute(verb, url)<br>yes: fresh client, full literal URL |
77
+ | github.com/gojek/heimdall/v7 | not yet | no: httpclient.NewClient().Get(url, headers)<br>no: Post(url, body, headers) |
78
+ | github.com/hashicorp/go-cleanhttp | not yet | no: cleanhttp.DefaultPooledClient() returns *http.Client; then Get |
79
+ | github.com/hashicorp/go-retryablehttp | partly | yes: package-level retryablehttp.Get<br>yes: NewClient then Post<br>no: retryablehttp.NewRequest then Do<br>no: StandardClient() gives a plain *http.Client |
80
+ | github.com/imroc/req/v3 | partly | no: req.C().SetBaseURL(); R().SetPathParam().Get<br>no: R().SetBody().Post<br>yes: package-level req.Get with a full URL<br>no: fluent client.Delete(url).Do() |
81
+ | github.com/parnurzeal/gorequest | supported | yes: gorequest.New().Get(url).End()<br>yes: Post(url).Send(json).End() |
82
+ | github.com/valyala/fasthttp (client) | partly | yes: fasthttp.Get(dst, url)<br>no: AcquireRequest, SetRequestURI, SetMethod, Client.Do |
83
+ | github.com/zeromicro/go-zero/rest/httpc | not yet | no: httpc.Do(ctx, verb, url-with-:id, reqStruct) |
84
+ | gopkg.in/h2non/gentleman.v2 | not yet | no: URL, Request, Method, Path, Send |
85
+ | oapi-codegen generated client | not yet | no: generated NewClientWithResponses(server) + GetSupplierWithResponse; generated code calls http.NewRequest |
86
+
87
+ ## The language's own HTTP client
88
+
89
+ 0 supported, 2 partly, 0 not yet.
90
+
91
+ | Name | Status | Ways of using it that were tested |
92
+ |---|---|---|
93
+ | net/http | partly | yes: http.Get with a literal URL<br>yes: http.Get with literal base plus string concatenation<br>no: http.Get with fmt.Sprintf building the URL<br>yes: http.Post with a base held in a package constant<br>partly: http.PostForm<br>yes: http.Head<br>no: http.NewRequest with a verb constant, then a configured http.Client's Do<br>no: http.NewRequestWithContext with a verb literal, then http.DefaultClient.Do, base from os.Getenv<br>no: url.JoinPath builds the URL, http.Client value's Get<br>yes: *http.Client held on a struct field, base on another field set from config<br>no: net/http/httputil reverse proxy to a fixed target<br>yes: plain http.Get to a grpc-gateway REST mapping |
94
+ | net/rpc | partly | no: rpc.DialHTTP then client.Call("Type.Method", args, &reply)<br>partly: asynchronous client.Go<br>yes: jsonrpc.Dial then Call |
95
+
96
+ ## gRPC
97
+
98
+ 2 supported, 3 partly, 4 not yet.
99
+
100
+ | Name | Status | Ways of using it that were tested |
101
+ |---|---|---|
102
+ | connectrpc.com/connect (client) | supported | yes: connect-go: {pkg}connect.New{S}Client(http.DefaultClient, baseURL) then client.M(ctx, connect.NewRequest(...)) (plan 8.4)<br>yes: the same client with connect.WithGRPC() |
103
+ | connectrpc.com/connect (server) | supported | yes: connect-go: path, h := {pkg}connect.New{S}Handler(&impl{}); mux.Handle(path, h) (plan 8.4) |
104
+ | github.com/go-kratos/kratos (gRPC transport) | not yet | no: kratos gRPC transport: pb.Register{S}Server(grpcSrv, svc) via kratos grpc.NewServer |
105
+ | github.com/grpc-ecosystem/grpc-gateway/v2 | partly | yes: grpc-gateway REST mapping from option (google.api.http) in the .proto, incl. additional_bindings (plan 8.4)<br>yes: pb.Register{S}HandlerFromEndpoint(ctx, mux, addr, opts)<br>no: pb.Register{S}HandlerServer(ctx, mux, impl) in-process |
106
+ | github.com/twitchtv/twirp | not yet | no: twirp New{S}Server(impl) mounted at server.PathPrefix(); path /twirp/{pkg}.{S}/{M}<br>no: twirp New{S}ProtobufClient(baseURL, httpClient) then client.M |
107
+ | go-micro.dev/v4 | not yet | no: go-micro service handler registration |
108
+ | google.golang.org/grpc (client) | partly | yes: conn from grpc.NewClient(literal target), then pb.New{S}Client(conn) stored on a struct field typed pb.{S}Client<br>yes: server-streaming client call returning a stream<br>yes: deprecated grpc.Dial(os.Getenv(...)) and a local client variable<br>no: grpc.DialContext with a dns:/// target (plan 8.6)<br>yes: conn.Invoke with the full wire path literal (plan 8.3 literal_path)<br>no: dynamic client through grpcreflect (plan 8.3: not covered) |
109
+ | google.golang.org/grpc (server) | partly | yes: server struct embedding pb.Unimplemented{S}Server, unary method (plan row grpc-go-unimplemented)<br>no: pb.Register{S}Server(s, impl) registration (plan section 3, go)<br>yes: server-streaming method M(req, stream pb.S_MServer) error (plan 8.2)<br>yes: client-streaming method M(stream pb.S_MServer) error (plan 8.2)<br>yes: bidirectional streaming method (plan 8.2)<br>yes: hand-written grpc.ServiceDesc literal + RegisterService (plan 8.3, keyed-literal reader)<br>no: grpc_health_v1.RegisterHealthServer(s, health.NewServer())<br>yes: reflection.Register(s) must NOT become a route (plan 8.3)<br>yes: checked-in generated orders_grpc.pb.go: the Unimplemented base's methods and the generated client's c.cc.Invoke must NOT become routes or calls (plan trap T5) |
110
+ | storj.io/drpc | not yet | no: storj drpc generated DRPC{S} interfaces |
111
+
112
+ ## Databases and data stores
113
+
114
+ 13 supported, 10 partly, 25 not yet.
115
+
116
+ | Name | Status | Ways of using it that were tested |
117
+ |---|---|---|
118
+ | cloud.google.com/go/bigquery | not yet | no: client.Query(sql).Read<br>no: Dataset().Table().Inserter().Put |
119
+ | cloud.google.com/go/firestore | supported | yes: Collection().Doc().Get/Set<br>yes: Collection().Where().Documents().GetAll |
120
+ | cloud.google.com/go/spanner | partly | partly: Single().Query(ctx, spanner.Statement{SQL: ...})<br>yes: spanner.Insert(table, cols, vals) passed to Apply |
121
+ | database/sql | partly | yes: sql.Open + QueryContext with the query in a constant<br>yes: ExecContext with an inline INSERT<br>yes: transaction: BeginTx, PrepareContext(DELETE), QueryRowContext(SELECT count)<br>partly: main reads or writes a table or collection that a service also owns (the cross-service data link) |
122
+ | entgo.io/ent | not yet | no: client.Review.Query().Where().All / Create().Save |
123
+ | github.com/aerospike/aerospike-client-go/v7 | not yet | no: github.com/aerospike/aerospike-client-go/v7 basic read/write |
124
+ | github.com/aws/aws-sdk-go (v1 dynamodb, s3) | not yet | no: github.com/aws/aws-sdk-go (v1 dynamodb, s3) basic read/write |
125
+ | github.com/aws/aws-sdk-go-v2/service/dynamodb | supported | yes: PutItem with TableName: aws.String(literal)<br>yes: GetItem with TableName from a constant<br>yes: Query |
126
+ | github.com/aws/aws-sdk-go-v2/service/s3 | partly | yes: PutObject with Bucket literal<br>no: GetObject with Bucket from os.Getenv<br>yes: manager.NewUploader(client).Upload |
127
+ | github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos | not yet | no: github.com/Azure/azure-sdk-for-go/sdk/data/azcosmos basic read/write |
128
+ | github.com/Azure/azure-sdk-for-go/sdk/storage/azblob | not yet | no: github.com/Azure/azure-sdk-for-go/sdk/storage/azblob basic read/write |
129
+ | github.com/bradfitz/gomemcache | partly | partly: mc.Set(&memcache.Item{Key: k}) and mc.Get(k) |
130
+ | github.com/ClickHouse/clickhouse-go/v2 | supported | yes: conn.Query(ctx, sql)<br>yes: PrepareBatch(ctx, "INSERT INTO t") |
131
+ | github.com/dgraph-io/badger | not yet | no: github.com/dgraph-io/badger basic read/write |
132
+ | github.com/doug-martin/goqu/v9 | supported | yes: goqu From(table).Where().ScanVals<br>yes: Insert(table).Rows().Executor().Exec() |
133
+ | github.com/elastic/go-elasticsearch/v8 | partly | partly: es.Index(index, body)<br>yes: es.Search(es.Search.WithIndex(name))<br>no: typed client Search().Index(name).Do |
134
+ | github.com/go-pg/pg/v10 | not yet | no: db.Model(&v).Where().Select() and Insert with pg:"table" tag |
135
+ | github.com/go-sql-driver/mysql | supported | yes: sql.Open("mysql", dsn) then Query |
136
+ | github.com/gocql/gocql | supported | yes: session.Query(cql).Exec() / .Iter() |
137
+ | github.com/gocraft/dbr/v2 | not yet | no: github.com/gocraft/dbr/v2 basic read/write |
138
+ | github.com/gomodule/redigo | not yet | no: conn.Do("COMMAND", key, ...) |
139
+ | github.com/hashicorp/consul/api (KV) | not yet | no: github.com/hashicorp/consul/api (KV) basic read/write |
140
+ | github.com/influxdata/influxdb-client-go/v2 | not yet | no: github.com/influxdata/influxdb-client-go/v2 basic read/write |
141
+ | github.com/jackc/pgx/v5 | partly | yes: pgx.Connect then conn.QueryRow<br>yes: pgxpool.New then pool.Exec<br>yes: pool.Query<br>no: pgx.Batch Queue<br>yes: CopyFrom with pgx.Identifier{table} |
142
+ | github.com/jmoiron/sqlx | partly | yes: db.Select(&dest, query)<br>no: db.Get with db.Rebind(query)<br>yes: NamedExec INSERT<br>yes: Queryx<br>yes: MustExec |
143
+ | github.com/lib/pq | supported | yes: Exec with pq.Array argument<br>yes: COPY with pq.CopyIn(table, cols...) |
144
+ | github.com/Masterminds/squirrel | partly | yes: Select().From(table).RunWith(db).Query()<br>no: Insert(table).ToSql() then db.Exec |
145
+ | github.com/mattn/go-sqlite3 and modernc.org/sqlite | supported | yes: sql.Open("sqlite3", file) then Exec<br>yes: sql.Open("sqlite", file) then QueryRow |
146
+ | github.com/meilisearch/meilisearch-go | not yet | no: github.com/meilisearch/meilisearch-go basic read/write |
147
+ | github.com/milvus-io/milvus-sdk-go/v2 | not yet | no: github.com/milvus-io/milvus-sdk-go/v2 basic read/write |
148
+ | github.com/minio/minio-go/v7 | supported | yes: minio PutObject/GetObject(ctx, bucket, object, ...) |
149
+ | github.com/neo4j/neo4j-go-driver/v5 | supported | yes: neo4j.ExecuteQuery(ctx, driver, cypher) and session.Run(ctx, cypher) |
150
+ | github.com/olivere/elastic/v7 | not yet | no: github.com/olivere/elastic/v7 basic read/write |
151
+ | github.com/opensearch-project/opensearch-go | not yet | no: github.com/opensearch-project/opensearch-go basic read/write |
152
+ | github.com/qdrant/go-client | not yet | no: github.com/qdrant/go-client basic read/write |
153
+ | github.com/redis/go-redis/v9 | supported | yes: Set/Get/HSet/LPush with literal or built keys<br>yes: Pipeline commands then Exec<br>yes: NewClusterClient then Del |
154
+ | github.com/redis/rueidis | not yet | no: client.Do(ctx, client.B().Set().Key(k).Value(v).Build()) |
155
+ | github.com/upper/db/v4 | not yet | no: github.com/upper/db/v4 basic read/write |
156
+ | github.com/uptrace/bun | partly | yes: NewSelect().Model(&slice) with bun:"table:..." tag<br>partly: NewInsert().Model(&v).Exec<br>yes: NewSelect().Table(name)<br>yes: NewRaw SQL |
157
+ | github.com/volatiletech/sqlboiler/v4 | not yet | no: github.com/volatiletech/sqlboiler/v4 basic read/write |
158
+ | go.etcd.io/bbolt | not yet | no: tx.Bucket([]byte(name)).Put/Get inside Update/View closures |
159
+ | go.etcd.io/etcd/client/v3 | not yet | no: clientv3 Put/Get with key or prefix |
160
+ | go.mongodb.org/mongo-driver | supported | yes: Database().Collection() then FindOne/InsertOne/UpdateOne<br>yes: one-line chain Database().Collection().Aggregate |
161
+ | go.mongodb.org/mongo-driver/v2 | supported | yes: mongo-driver v2 (Connect without ctx), Find/DeleteMany |
162
+ | gocloud.dev/blob | not yet | no: gocloud.dev/blob basic read/write |
163
+ | gorm.io/gorm | partly | yes: model-based queries: First, Where().Order().Find<br>yes: Create(&model)<br>yes: Model(&Order{}).Where().Update<br>yes: Delete(&Order{}, id)<br>yes: Table(name) names the table<br>yes: Raw SQL through GORM<br>yes: Exec SQL through GORM<br>no: model with TableName() override |
164
+ | sqlc (generated code) | not yet | no: sqlc generated Queries: SQL in const strings, called through q.db.QueryRow/Exec |
165
+ | xorm.io/xorm | not yet | no: engine.Where().Get(&model) with TableName()<br>no: engine.Table(name).Where().Count() |
166
+
167
+ ## Messaging and events (queues, topics, streams)
168
+
169
+ 5 supported, 14 partly, 15 not yet.
170
+
171
+ | Name | Status | Ways of using it that were tested |
172
+ |---|---|---|
173
+ | channels (in-process bus) | not yet | no: in-process event bus on channels shared between packages (Publish/Subscribe by topic string) |
174
+ | cloud.google.com/go/pubsub | partly | no: client.Topic(name).Publish(ctx, msg), inline or through a variable<br>partly: client.Subscription(name).Receive(ctx, cb) |
175
+ | cloud.google.com/go/pubsub/v2 (Publisher/Subscriber API) | not yet | no: cloud.google.com/go/pubsub/v2 (Publisher/Subscriber API) basic use |
176
+ | github.com/apache/pulsar-client-go | supported | yes: CreateProducer(pulsar.ProducerOptions{Topic}) then Send<br>yes: client.Subscribe(pulsar.ConsumerOptions{Topic, SubscriptionName}) then Receive |
177
+ | github.com/aws/aws-sdk-go v1 (sqs, sns) | not yet | no: github.com/aws/aws-sdk-go v1 (sqs, sns) basic use |
178
+ | github.com/aws/aws-sdk-go-v2 (sqs, sns, eventbridge, kinesis) | partly | yes: SQS SendMessage with QueueUrl literal<br>no: SQS ReceiveMessage with QueueUrl from os.Getenv<br>yes: SNS Publish with TopicArn literal<br>no: EventBridge PutEvents with EventBusName and DetailType<br>yes: Kinesis PutRecord with StreamName |
179
+ | github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus | partly | yes: client.NewSender(queue).SendMessage<br>no: NewReceiverForQueue(queue).ReceiveMessages |
180
+ | github.com/centrifugal/centrifuge | not yet | no: github.com/centrifugal/centrifuge basic use |
181
+ | github.com/cloudevents/sdk-go/v2 | not yet | no: cloudevents.NewClientHTTP(WithPort) + StartReceiver(ctx, fn)<br>no: c.Send(cloudevents.ContextWithTarget(ctx, url), event) |
182
+ | github.com/confluentinc/confluent-kafka-go/v2 | supported | yes: Produce(&kafka.Message{TopicPartition: kafka.TopicPartition{Topic: &topic}})<br>yes: SubscribeTopics([]string{...}, nil)<br>yes: Subscribe(topic, nil) |
183
+ | github.com/dapr/go-sdk | partly | yes: Dapr client.PublishEvent(ctx, pubsub, topic, data)<br>partly: service AddTopicEventHandler(&common.Subscription{PubsubName, Topic, Route}, h) |
184
+ | github.com/eclipse/paho.mqtt.golang | partly | partly: client.Publish(topic, qos, retained, payload)<br>no: client.Subscribe(filter-with-+, qos, cb) |
185
+ | github.com/go-co-op/gocron (scheduler) | not yet | no: github.com/go-co-op/gocron (scheduler) basic use |
186
+ | github.com/go-redis/redis/v8 | not yet | no: github.com/go-redis/redis/v8 basic use |
187
+ | github.com/gocraft/work | not yet | no: github.com/gocraft/work basic use |
188
+ | github.com/hibiken/asynq | partly | yes: client.Enqueue(asynq.NewTask(type, payload))<br>yes: mux.HandleFunc(type, fn)<br>no: mux.Handle(constType, handlerType) |
189
+ | github.com/IBM/sarama | partly | yes: SyncProducer.SendMessage(&sarama.ProducerMessage{Topic: ...})<br>yes: ProducerMessage built in a variable, then SendMessage(msg)<br>no: AsyncProducer.Input() <- msg<br>no: ConsumerGroup.Consume(ctx, []string{topic}, handler) with a ConsumerGroupHandler<br>yes: Consumer.ConsumePartition(topic, partition, offset) |
190
+ | github.com/lib/pq (LISTEN/NOTIFY) | supported | yes: pq.NewListener + Listen(channel): Postgres LISTEN/NOTIFY as an event bus |
191
+ | github.com/nats-io/nats.go | partly | yes: nc.Publish(subject, data)<br>partly: nc.Subscribe(subject, callback)<br>no: nc.QueueSubscribe(subject, queue, cb)<br>no: nc.Request(subject, data, timeout) and a responder that calls m.Respond<br>yes: nc.JetStream() then js.Publish / js.Subscribe<br>partly: jetstream.New(nc); stream.CreateOrUpdateConsumer(ConsumerConfig{FilterSubject}); cons.Consume(cb); js.Publish(ctx, subj, data) |
192
+ | github.com/nsqio/go-nsq | partly | yes: producer.Publish(topic, body)<br>no: nsq.NewConsumer(topic, channel, cfg) + AddHandler(HandleMessage) |
193
+ | github.com/rabbitmq/amqp091-go | partly | yes: PublishWithContext(ctx, exchange, routingKey, ...)<br>yes: Consume(queue, ...)<br>no: QueueBind(queue, routingKey, exchange): joins a routing key to a queue |
194
+ | github.com/redis/go-redis/v9 (pub/sub, streams) | partly | yes: rdb.Publish(ctx, channel, msg)<br>yes: rdb.Subscribe(ctx, channel) then sub.Channel()<br>yes: XAdd(ctx, &redis.XAddArgs{Stream: ...})<br>no: XReadGroup(ctx, &redis.XReadGroupArgs{Streams: []string{name, ">"}}) |
195
+ | github.com/RichardKnop/machinery/v2 | not yet | no: server.SendTask(&tasks.Signature{Name}) and RegisterTask(name, fn) |
196
+ | github.com/riverqueue/river | partly | partly: client.Insert(ctx, args, nil) where args has Kind() string<br>no: river.AddWorker(workers, &Worker{}) with Work(ctx, *river.Job[Args]) |
197
+ | github.com/robfig/cron/v3 (scheduler) | not yet | no: github.com/robfig/cron/v3 (scheduler) basic use |
198
+ | github.com/segmentio/kafka-go | partly | yes: kafka.NewReader(kafka.ReaderConfig{Topic}) then ReadMessage/FetchMessage<br>partly: kafka.Writer{Topic: ...} then WriteMessages<br>yes: Writer with no topic; Topic on each kafka.Message |
199
+ | github.com/Shopify/sarama (old import path) | not yet | no: github.com/Shopify/sarama (old import path) basic use |
200
+ | github.com/streadway/amqp | supported | yes: legacy streadway/amqp Consume and Publish (same API as amqp091) |
201
+ | github.com/ThreeDotsLabs/watermill | partly | partly: publisher.Publish(topic, msg)<br>partly: router.AddHandler(name, subTopic, sub, pubTopic, pub, fn)<br>no: router.AddNoPublisherHandler(name, topic, sub, fn) |
202
+ | github.com/twmb/franz-go | supported | yes: kgo.NewClient(kgo.ConsumeTopics(...)) then PollFetches<br>yes: Produce/ProduceSync(ctx, &kgo.Record{Topic: ...}) |
203
+ | go-micro.dev broker | not yet | no: go-micro.dev broker basic use |
204
+ | go.etcd.io/etcd/client/v3 (Watch) | not yet | no: clientv3 Watch on a prefix (change notifications) |
205
+ | go.temporal.io/sdk (workflows and activities) | not yet | no: go.temporal.io/sdk (workflows and activities) basic use |
206
+ | slack-go, twilio-go, sendgrid-go (SaaS API calls) | not yet | no: slack-go, twilio-go, sendgrid-go (SaaS API calls) basic use |
207
+
208
+ ## Build tools and package managers
209
+
210
+ 8 supported, 0 partly, 0 not yet.
211
+
212
+ | Name | Status | Ways of using it that were tested |
213
+ |---|---|---|
214
+ | bazel (rules_go + gazelle) | supported | yes: MODULE.bazel + BUILD.bazel with go_binary / go_library / go_test, one root go.mod |
215
+ | bazel (WORKSPACE, legacy) | supported | yes: WORKSPACE + BUILD files and no go.mod at all |
216
+ | dep / glide (pre-modules) | supported | yes: Gopkg.toml (dep) and glide.yaml, no go.mod, GOPATH import paths |
217
+ | go modules | supported | yes: one go.mod at the root, package main plus one sub-package<br>yes: several go.mod in one repo, joined by one-line `replace X => ../path`<br>yes: replace written as a block: `replace ( X => ../path )`<br>yes: vendored dependencies in vendor/ with vendor/modules.txt |
218
+ | go workspaces | supported | yes: go.work with a `use ( ... )` block, no replace directives<br>yes: go.work with one `use` per line and a workspace-level replace |
219
+ | goreleaser | supported | yes: .goreleaser.yaml declaring two builds (main: ./cmd/x) from one module |
220
+ | mage | supported | yes: magefile.go (`//go:build mage`, package main) at the root of a library module |
221
+ | make / Task | supported | yes: Makefile and Taskfile.yml that build two binaries from one module |
222
+
223
+ ## Project and folder layouts
224
+
225
+ 6 supported, 0 partly, 0 not yet.
226
+
227
+ | Name | Status | Ways of using it that were tested |
228
+ |---|---|---|
229
+ | go build | supported | yes: bin/ and dist/ build output, and a coverage profile |
230
+ | go build (cgo) | supported | yes: Go package with `import "C"` and .c/.h files beside it |
231
+ | go build (tags) | supported | yes: platform files: _windows.go, _linux.go, and //go:build js && wasm |
232
+ | go modules | supported | yes: golang-standards layout: cmd/, internal/, pkg/, api/, configs/, scripts/, test/<br>yes: one go.mod with two programs under cmd/api and cmd/worker sharing internal/<br>yes: a module nested inside another module's folder (examples/ and tools/ with their own go.mod)<br>yes: tools.go with `//go:build tools` importing code generators<br>yes: major version in a subdirectory: v2/ with its own go.mod (module .../v2)<br>yes: a library with examples/<name>/main.go programs inside the same module |
233
+ | go test | supported | yes: _test.go beside code, external test package (package x_test), testdata/ holding .go fixtures |
234
+ | protoc / go generate | supported | yes: generated *.pb.go and `// Code generated ... DO NOT EDIT.` files inside the module, plus a //go:generate line |
235
+
236
+ ## Deployment files
237
+
238
+ 17 supported, 0 partly, 0 not yet.
239
+
240
+ | Name | Status | Ways of using it that were tested |
241
+ |---|---|---|
242
+ | aws sam | supported | yes: template.yaml with AWS::Serverless::Function CodeUri per service |
243
+ | docker buildx bake | supported | yes: docker-bake.hcl targets with context |
244
+ | docker compose | supported | yes: docker-compose.yml, `build: ./services/x` string form, plus image-only infra<br>yes: `build: {context: ., dockerfile: services/x/Dockerfile}`: context is the repo root<br>yes: deploy/docker-compose.yml with `../services/x` contexts<br>yes: compose.yaml plus compose.override.yaml, `profiles`, `extends`, and an `image:` + `build:` service |
245
+ | dockerfile | supported | yes: a Dockerfile in each service folder and nothing else<br>yes: docker/<svc>/Dockerfile kept apart from the code |
246
+ | fly.io | supported | yes: fly.toml per service with app = "name" |
247
+ | github actions | supported | yes: dorny/paths-filter with one named filter per service<br>yes: a build matrix over services with working-directory: services/${{ matrix.service }} |
248
+ | gitlab ci | supported | yes: .gitlab-ci.yml jobs with rules:changes per service |
249
+ | google app engine | supported | yes: app.yaml per service (runtime go122, service: name) plus dispatch.yaml |
250
+ | helm | supported | yes: charts/<svc>/Chart.yaml type application, one library chart, one umbrella chart with dependencies |
251
+ | heroku procfile | supported | yes: Procfile inside each service folder (web and worker process types) |
252
+ | kubernetes | supported | yes: multi-document manifest: Deployment `shop-orders-api` (name differs from folder), Service, CronJob `billing` |
253
+ | kubernetes (kustomize) | supported | yes: kustomize base + overlays; workloads in base, overlays patch them |
254
+ | kubernetes + ko | supported | yes: `image: ko://example.com/shop/orders` naming the Go import path to build |
255
+ | render | supported | yes: one render.yaml at the root listing services with rootDir |
256
+ | serverless framework | supported | yes: serverless.yml per service, provider.runtime provided.al2, functions with handler bootstrap |
257
+ | skaffold | supported | yes: skaffold.yaml build.artifacts with context per service |
258
+ | vercel | supported | yes: vercel.json with Go serverless functions in api/*.go |
@@ -0,0 +1,226 @@
1
+ # Supported in Java
2
+
3
+ <!-- GENERATED by scripts/gen-supported-docs.js. Do not edit by hand: run the script again. -->
4
+ <!-- source: catalog/java.json; catalog/java.structure.json -->
5
+ <!-- measured: coverage corpus 1bb4ebb, niro-local 2b30d4fd -->
6
+
7
+ This page lists the Java libraries, frameworks and build tools Niro was tested against, and whether it recognised each one.
8
+
9
+ **What the marks mean.**
10
+
11
+ - **Supported:** Niro recognised every way of using it that the test code tries.
12
+ - **Partly:** Niro recognised some of those ways, or recognised one only in part.
13
+ - **Not yet:** Niro did not recognise it in the test code.
14
+
15
+ The test code is made up for the purpose: one small service per library, with the names invented. So "supported" means Niro recognised it there. It is good evidence, but it is not a promise about every codebase. If Niro misses something in your code, the coverage audit reports the gap on its own (see [coverage-audit-and-consent.md](coverage-audit-and-consent.md)).
16
+ <!-- source: niro-coverage-corpus README.md ("Synthetic test code ... All names are made up"); catalog status merged pairs one to one with measured found -->
17
+
18
+ The test catalog also holds 8 look-alike cases for Java: code that Niro must NOT take for a route, a call or a store. They test that Niro ignores the look-alike, so they are left out of this page and its counts.
19
+ <!-- source: catalog/java.json and catalog/java.structure.json, rows marked as traps (scripts/gen-supported-docs.js isTrap) -->
20
+
21
+ ## Web frameworks and HTTP servers (the routes your code serves)
22
+
23
+ 18 supported, 1 partly, 3 not yet.
24
+
25
+ | Name | Status | Ways of using it that were tested |
26
+ |---|---|---|
27
+ | Armeria | partly | yes: annotated service @Get(path) / @Post(path)<br>no: Server.builder().service(path, (ctx, req) -> ...) |
28
+ | AWS SAM template.yaml | supported | yes: AWS::Serverless::Function (Runtime java17, Handler package.Class::method or package.Class) with Events Type HttpApi or Api Path and Method |
29
+ | Azure Functions (Java) | supported | yes: @FunctionName("X") method with a parameter annotated @HttpTrigger(methods = {HttpMethod.GET}, route = "x/{id}"), served under the host.json routePrefix<br>yes: @HttpTrigger with no route and no methods: the route is the @FunctionName name and every verb |
30
+ | Eclipse Jetty (embedded) | supported | yes: ServletContextHandler.addServlet(holder or class, pattern) |
31
+ | Helidon SE 4 | supported | yes: HttpRouting.Builder.get(path, handler).post(path, lambda) |
32
+ | Javalin | supported | yes: app.get(path, lambda) / app.post(path, Class::method)<br>yes: ApiBuilder path(prefix, () -> { get(h); post(sub, h); }) in config.router.apiBuilder |
33
+ | JAX-RS (jakarta.ws.rs: Jersey, RESTEasy, Quarkus REST) | supported | yes: @Path on class and method, @GET/@POST/@DELETE |
34
+ | JAX-RS (javax.ws.rs: Dropwizard, Java EE 8) | supported | yes: @Path / @GET / @PUT in the javax namespace |
35
+ | Jooby | not yet | no: get(path, ctx -> ...) inside the Jooby subclass initialiser |
36
+ | Micronaut HTTP | supported | yes: @Controller(prefix) with @Get(path) and @Post (no path) |
37
+ | Play Framework (Java) | not yet | no: conf/routes lines: VERB path controllers.X.method() |
38
+ | Quarkus reactive routes | supported | yes: @RouteBase(path) + @Route(path, methods) |
39
+ | Quarkus REST (RESTEasy Reactive) | supported | yes: plain JAX-RS @Path/@GET in a Quarkus app |
40
+ | Ratpack | supported | yes: chain.get(path, handler) with no leading slash<br>yes: chain.prefix(prefix, sub -> sub.post(path, handler)) |
41
+ | Serverless Framework serverless.yml | supported | yes: functions.<name>.handler package.Class[::method] with events httpApi or http |
42
+ | Spark Java | supported | yes: static get(path, (req, res) -> ...) and Spark.post(...) |
43
+ | Spring Boot | supported | yes: new ServletRegistrationBean<>(new XServlet(), path) |
44
+ | Spring Web MVC | supported | yes: @RestController + class @RequestMapping prefix + @GetMapping/@PostMapping/@PutMapping/@DeleteMapping<br>yes: @RequestMapping(path = {a, b}, method = RequestMethod.POST) on @Controller + @ResponseBody<br>yes: mapping path held in a static final String constant |
45
+ | Spring WebFlux | supported | yes: annotated @RestController returning Mono |
46
+ | Spring WebFlux (functional) | supported | yes: RouterFunctions.route().GET(path, handler).POST(...).build()<br>yes: static route(GET(path), handler) from RequestPredicates<br>yes: nest(path(prefix), route(GET(sub), handler)) |
47
+ | Undertow | not yet | no: Handlers.routing().get(path, handler).post(path, lambda) |
48
+ | Vert.x Web | supported | yes: router.get(path).handler(h) / router.post(path).handler(lambda)<br>yes: router.route(HttpMethod.X, path).handler(h) |
49
+
50
+ ## The language's own HTTP server
51
+
52
+ 3 supported, 0 partly, 1 not yet.
53
+
54
+ | Name | Status | Ways of using it that were tested |
55
+ |---|---|---|
56
+ | com.sun.net.httpserver (JDK) | supported | yes: HttpServer.createContext(path, lambda)<br>yes: createContext(path, new XHandler()) with a class implementing HttpHandler<br>yes: createContext(path, Class::method), verb read inside from getRequestMethod()<br>yes: HttpsServer.createContext |
57
+ | Servlet API (jakarta.servlet) | supported | yes: @WebServlet("/path") on an HttpServlet subclass, verbs from doGet/doPost<br>yes: @WebServlet(name=, urlPatterns={a, b})<br>yes: ServletContext.addServlet(name, X.class).addMapping(path) |
58
+ | Servlet API (javax.servlet) | supported | yes: @WebServlet(urlPatterns = ...) in the old javax namespace |
59
+ | Servlet API (WEB-INF/web.xml) | not yet | no: <servlet-mapping> url-pattern naming a servlet-class |
60
+
61
+ ## HTTP client libraries (the calls your code makes to other services)
62
+
63
+ 14 supported, 1 partly, 5 not yet.
64
+
65
+ | Name | Status | Ways of using it that were tested |
66
+ |---|---|---|
67
+ | Apache HttpClient 4 | supported | yes: client.execute(new HttpGet/HttpPost/HttpDelete(url)) |
68
+ | Apache HttpClient 5 | supported | yes: client.execute(new HttpGet(url), responseHandler) |
69
+ | Apache HttpClient 5 Fluent | supported | yes: Request.get(url).execute() / Request.post(url) |
70
+ | AsyncHttpClient | supported | yes: client.prepareGet(url).execute() / preparePost |
71
+ | Google HTTP Client | not yet | no: factory.buildGetRequest(new GenericUrl(url)).execute() |
72
+ | JAX-RS client (Jersey, RESTEasy) | supported | yes: ClientBuilder.newClient().target(base).path(p).request().get()/post() |
73
+ | Jetty HttpClient | supported | yes: httpClient.GET(url) / newRequest(url).method(..).send() |
74
+ | Micronaut HTTP client | not yet | no: @Client(base) interface with @Get(path) |
75
+ | MicroProfile REST Client (Quarkus, Open Liberty) | supported | yes: @RegisterRestClient(baseUri) interface with @Path + @GET |
76
+ | OkHttp | supported | yes: client.newCall(new Request.Builder().url(x)[.post(body)].build()).execute() |
77
+ | OpenFeign (plain) | not yet | no: @RequestLine("VERB /path") with Feign.builder().target(Api.class, base) |
78
+ | Reactor Netty HttpClient | supported | yes: HttpClient.create().baseUrl(base).get().uri(path) |
79
+ | Retrofit | not yet | no: interface with @GET/@POST and Retrofit.Builder().baseUrl(base) |
80
+ | Spring Cloud OpenFeign | supported | yes: @FeignClient(name, url) interface with @GetMapping/@PostMapping<br>yes: @FeignClient(name = service) with no url (service discovery) |
81
+ | Spring HTTP interface (@HttpExchange) | not yet | no: interface with @HttpExchange(base) and @GetExchange/@PostExchange |
82
+ | Spring RestClient (6.1+) | supported | yes: RestClient.create(base).get().uri(path, vars).retrieve().body(T) |
83
+ | Spring RestTemplate | supported | yes: getForObject(literal url + id, type)<br>yes: postForEntity(baseUrl from @Value("${...}") + path)<br>yes: exchange(url template, HttpMethod.PUT, entity, type, vars)<br>yes: delete(url) and postForObject(url, ...) |
84
+ | Spring WebClient | supported | yes: WebClient.create(base).get().uri(path, vars).retrieve()<br>yes: WebClient.builder().baseUrl(base with a path).build() then .uri(sub) |
85
+ | Unirest for Java | supported | yes: Unirest.get(url with {param}).routeParam(..) / Unirest.post(url) |
86
+ | Vert.x WebClient | partly | partly: client.get(port, host, path).send()<br>yes: client.getAbs/postAbs(absolute url).send() |
87
+
88
+ ## The language's own HTTP client
89
+
90
+ 1 supported, 1 partly, 1 not yet.
91
+
92
+ | Name | Status | Ways of using it that were tested |
93
+ |---|---|---|
94
+ | java.net.http.HttpClient (JDK 11+) | partly | partly: send(HttpRequest.newBuilder().uri(URI.create(x)).GET().build(), handler)<br>yes: sendAsync / send with .POST(BodyPublishers...)<br>yes: HttpRequest.newBuilder(URI) with no .uri() step |
95
+ | java.net.HttpURLConnection (JDK) | not yet | no: (HttpURLConnection) new URL(x).openConnection() then setRequestMethod("POST")<br>no: URI.create(x).toURL().openConnection(), default GET |
96
+ | java.net.URL (JDK) | supported | yes: new URL(x).openStream() |
97
+
98
+ ## gRPC
99
+
100
+ 7 supported, 0 partly, 0 not yet.
101
+
102
+ | Name | Status | Ways of using it that were tested |
103
+ |---|---|---|
104
+ | Armeria gRPC | supported | yes: GrpcService.builder().addService(impl of the generated base) |
105
+ | grpc-java | supported | yes: class extends {S}Grpc.{S}ImplBase with @Override per RPC (unary, server stream, client stream)<br>yes: class implements {S}Grpc.AsyncService, BindableService |
106
+ | grpc-java client | supported | yes: {S}Grpc.newBlockingStub(channel).rpc(req), channel from ManagedChannelBuilder.forAddress/forTarget<br>yes: non-RPC stub step before the call: stub.withDeadlineAfter(..).rpc(req)<br>yes: {S}Grpc.newStub(channel).rpc(req, StreamObserver)<br>yes: {S}Grpc.newFutureStub(channel).rpc(req) returning ListenableFuture<br>yes: ClientCalls.blockingUnaryCall(channel, {S}Grpc.get{M}Method(), options, req) |
107
+ | grpc-spring-boot-starter (net.devh) | supported | yes: @GrpcService on a subclass of the generated base |
108
+ | grpc-spring-boot-starter (net.devh) client | supported | yes: @GrpcClient("name") on a stub field, address in application.yml |
109
+ | LogNet grpc-spring-boot-starter | supported | yes: @GRpcService on a subclass of the generated base |
110
+ | Quarkus gRPC | supported | yes: @GrpcService class implements the Mutiny interface {S}, methods return Uni |
111
+
112
+ ## Databases and data stores
113
+
114
+ 21 supported, 8 partly, 3 not yet.
115
+
116
+ | Name | Status | Ways of using it that were tested |
117
+ |---|---|---|
118
+ | AWS SDK v2 DynamoDB | supported | yes: dynamo.getItem(GetItemRequest.builder().tableName(name)...) |
119
+ | AWS SDK v2 DynamoDB Enhanced | supported | yes: enhanced.table(name, TableSchema.fromBean(..)).getItem |
120
+ | AWS SDK v2 S3 | supported | yes: s3.putObject(PutObjectRequest.builder().bucket(name)..) / getObjectAsBytes |
121
+ | DataStax Java driver (Cassandra) | partly | partly: session.execute(CQL string) / SimpleStatement.newInstance(CQL) |
122
+ | Ebean ORM | partly | partly: DB.find(X.class).where()...findList() / DB.save(x) |
123
+ | Elasticsearch Java client | supported | yes: client.search(s -> s.index(name)...) / client.index(i -> i.index(name)) |
124
+ | Hibernate ORM (native Session) | partly | partly: session.persist / session.get(X.class, id) / createQuery(HQL) |
125
+ | JDBC (java.sql, JDK) | supported | yes: DriverManager.getConnection(url) + createStatement().executeQuery(SQL)<br>yes: conn.prepareStatement(SQL) then executeUpdate/executeQuery<br>yes: conn.prepareCall("{call proc(?)}") |
126
+ | JDBC (javax.sql.DataSource) | supported | yes: dataSource.getConnection().createStatement().executeUpdate(SQL) |
127
+ | JDBI 3 | supported | yes: jdbi.withHandle(h -> h.createQuery(SQL)) / h.execute(SQL)<br>yes: SqlObject interface with @SqlQuery/@SqlUpdate |
128
+ | Jedis (Redis) | partly | partly: jedis.get/set on keys, JedisPooled.hincrBy |
129
+ | jOOQ | supported | yes: dsl.selectFrom(table("name")) / insertInto(table("name"))<br>yes: dsl.fetch(SQL string, binds) |
130
+ | JPA EntityManager (jakarta.persistence) | supported | yes: em.persist / em.find(X.class, id) / em.remove<br>yes: em.createQuery(JPQL naming the entity, X.class)<br>yes: em.createNativeQuery(SQL).executeUpdate() |
131
+ | Lettuce (Redis) | supported | yes: RedisClient.create(uri).connect().sync().get(key) / async().expire |
132
+ | Micronaut Data JDBC | supported | yes: @JdbcRepository interface extends CrudRepository<T, Id>, entity @MappedEntity(name) |
133
+ | MongoDB Java driver | partly | partly: db.getCollection(name).find / insertOne / deleteMany |
134
+ | MyBatis | supported | yes: @Mapper interface with @Select/@Insert SQL<br>yes: mapper XML <select id> bound to an interface method |
135
+ | MyBatis-Plus | supported | yes: interface extends BaseMapper<T>, entity @TableName, selectList/insert |
136
+ | Neo4j Java driver | partly | partly: session.run(Cypher, params) |
137
+ | Quarkus Hibernate ORM with Panache | not yet | no: entity extends PanacheEntity: list(..), persist(), count() |
138
+ | Redisson | not yet | no: redisson.getMap(name).put / getLock(name) |
139
+ | Spring cache abstraction | not yet | no: @Cacheable("cache-name") on a method |
140
+ | Spring Data Elasticsearch | supported | yes: interface extends ElasticsearchRepository<T, Id>, @Document(indexName) |
141
+ | Spring Data JDBC | supported | yes: interface extends CrudRepository<T, Id>, entity @Table(name) from data.relational |
142
+ | Spring Data JPA | supported | yes: interface extends JpaRepository<Entity, Id> with derived finders; entity @Table(name)<br>yes: @Query("SELECT o FROM Entity o ...") on a repository method<br>yes: @Query(value = SQL, nativeQuery = true) |
143
+ | Spring Data MongoDB | partly | yes: interface extends MongoRepository<T, Id>, @Document(name)<br>no: mongoTemplate.find(query, T.class, "collection") / insert(doc, "collection") |
144
+ | Spring Data R2DBC | supported | yes: interface extends R2dbcRepository<T, Id>, entity @Table(name) |
145
+ | Spring Data Redis | partly | partly: redisTemplate.opsForValue().get/set, opsForHash().put |
146
+ | Spring JDBC | supported | yes: jdbcTemplate.queryForList / update(SQL, args)<br>yes: NamedParameterJdbcTemplate.update(SQL with :names, map)<br>yes: new SimpleJdbcInsert(jdbc).withTableName(name).execute(map) |
147
+ | Spring JDBC JdbcClient (6.1+) | supported | yes: jdbcClient.sql(SQL).param(..).query(T).list() |
148
+ | Spring R2DBC DatabaseClient | supported | yes: client.sql(SQL).fetch()/all() |
149
+ | Vert.x SQL client | supported | yes: pool.query(SQL).execute() / preparedQuery(SQL).execute(tuple) |
150
+
151
+ ## Messaging and events (queues, topics, streams)
152
+
153
+ 14 supported, 7 partly, 4 not yet.
154
+
155
+ | Name | Status | Ways of using it that were tested |
156
+ |---|---|---|
157
+ | Apache Camel | not yet | no: RouteBuilder.configure(): from("kafka:topic?..").to("jms:queue:name") |
158
+ | Apache Kafka clients | supported | yes: producer.send(new ProducerRecord<>(topic, key, value))<br>yes: consumer.subscribe(List.of(topic)) + poll loop |
159
+ | Apache Pulsar client | supported | yes: client.newProducer().topic(name).create().send(..)<br>yes: client.newConsumer().topic(name).subscriptionName(..).subscribe() |
160
+ | AWS SDK v2 SNS | supported | yes: sns.publish(PublishRequest.builder().topicArn(arn)...) |
161
+ | AWS SDK v2 SQS | partly | yes: sqs.sendMessage(SendMessageRequest.builder().queueUrl(url)...)<br>no: sqs.receiveMessage(ReceiveMessageRequest.builder().queueUrl(url)...) |
162
+ | Azure Service Bus | partly | yes: new ServiceBusClientBuilder().sender().queueName(name).buildClient().sendMessage(..)<br>partly: builder.processor().queueName(name).processMessage(cb) |
163
+ | Eclipse Paho MQTT | supported | yes: client.publish(topic, msg) / client.subscribe(filter, listener) |
164
+ | Google Cloud Pub/Sub | partly | yes: Publisher.newBuilder(TopicName.of(project, topic)).build().publish(msg)<br>no: Subscriber.newBuilder(ProjectSubscriptionName.of(project, sub), receiver) |
165
+ | Jakarta Messaging (JMS) | partly | partly: class implements MessageListener { onMessage(..) } |
166
+ | Jakarta Messaging (JMS) classic API | supported | yes: session.createConsumer(session.createQueue(name)).setMessageListener(..)<br>yes: session.createProducer(session.createQueue(name)).send(msg) |
167
+ | Jakarta Messaging 2.0 simplified API | supported | yes: context.createConsumer(context.createQueue(name)) / createProducer().send(queue, body) |
168
+ | Java Message Service (javax.jms) | supported | yes: the classic API in the old javax namespace |
169
+ | Jedis pub/sub | supported | yes: jedis.publish(channel, msg) / jedis.subscribe(JedisPubSub, channel) |
170
+ | Kafka Streams | not yet | no: builder.stream(topic) ... .to(topic) |
171
+ | Micronaut Kafka | not yet | no: @KafkaListener class with @Topic method; @KafkaClient interface with @Topic method |
172
+ | NATS Java client (jnats) | supported | yes: connection.publish(subject, bytes)<br>yes: dispatcher.subscribe(subject) / connection.subscribe(subject) |
173
+ | RabbitMQ Java client | partly | yes: channel.basicPublish("", queue, props, body)<br>no: channel.basicConsume(queue, autoAck, DeliverCallback, CancelCallback)<br>no: basicConsume(queue, ack, new DefaultConsumer(ch) { handleDelivery(..) }) |
174
+ | SmallRye / MicroProfile Reactive Messaging (Quarkus) | not yet | no: @Incoming(channel), @Outgoing(channel), @Channel Emitter; channel to topic in application.properties |
175
+ | Spring AMQP (RabbitMQ) | partly | yes: rabbitTemplate.convertAndSend(routingKey, message) on the default exchange<br>partly: convertAndSend(exchange, routingKey, message)<br>yes: @RabbitListener(queues = "literal") |
176
+ | Spring application events (in-process) | supported | yes: publisher.publishEvent(obj) + @EventListener on the type |
177
+ | Spring Cloud AWS | supported | yes: @SqsListener("queue-name")<br>yes: sqsTemplate.send(queue, payload) |
178
+ | Spring Cloud Stream | partly | no: @Bean Consumer<T> name() bound in application.yml (name-in-0.destination)<br>partly: streamBridge.send(binding or destination, payload) |
179
+ | Spring Data Redis pub/sub | supported | yes: redisTemplate.convertAndSend(channel, msg) / container.addMessageListener(l, new ChannelTopic(ch)) |
180
+ | Spring for Apache Kafka | supported | yes: kafkaTemplate.send(topic, [key,] value)<br>yes: @KafkaListener(topics = "literal")<br>yes: @KafkaListener(topics = "${property}") resolved from application.yml |
181
+ | Spring JMS | supported | yes: jmsTemplate.convertAndSend(destination, payload)<br>yes: @JmsListener(destination = "literal") |
182
+
183
+ ## Build tools and package managers
184
+
185
+ 19 supported, 1 partly, 0 not yet.
186
+
187
+ | Name | Status | Ways of using it that were tested |
188
+ |---|---|---|
189
+ | Apache Ant | supported | yes: root build.xml calling <ant dir=...> per module; flat src/ folders; Main-Class in the jar manifest |
190
+ | Apache Ant + Ivy | supported | yes: ivy.xml per module naming the other module as a dependency, ivysettings.xml at the root |
191
+ | Bazel (Bzlmod, MODULE.bazel) | supported | yes: MODULE.bazel with bazel_dep, BUILD.bazel files loading rules_java |
192
+ | Bazel (WORKSPACE) | supported | yes: WORKSPACE at the root, BUILD per package with java_binary, java_library and java_test |
193
+ | Bndtools workspace (OSGi) | supported | yes: cnf/ plus one folder per bundle with bnd.bnd and flat src/ |
194
+ | Gradle (Groovy DSL) | supported | yes: settings.gradle include, application and Spring Boot services, java-library module, project(':x') dependency |
195
+ | Gradle (Kotlin DSL) | supported | yes: settings.gradle.kts include(...), `java-library` and Spring Boot plugin, implementation(project(":x")) |
196
+ | Gradle buildSrc | supported | yes: buildSrc with a precompiled convention plugin applied by id |
197
+ | Gradle composite build | supported | yes: includeBuild("platform/money") with the dependency by coordinates, substituted by Gradle |
198
+ | Gradle included build for convention plugins | supported | yes: pluginManagement { includeBuild("build-logic") } with a Plugin<Project> class; the service applies id("shop.service") |
199
+ | Gradle version catalog | supported | yes: gradle/libs.versions.toml, alias(libs.plugins.x) and typesafe project accessors implementation(projects.moneyLib) |
200
+ | Gradle war plugin | supported | yes: id 'war' with src/main/webapp/WEB-INF/web.xml |
201
+ | Gradle Wrapper | supported | yes: gradlew, gradlew.bat and gradle/wrapper next to a multi-project build |
202
+ | Maven | supported | yes: one pom.xml, src/main/java and src/test/java, target/ output<br>yes: reactor: parent pom packaging pom with <modules>, two Spring Boot services and a jar library<br>yes: <modules> nested two deep: root -> platform (pom) -> libraries, root -> apps (pom) -> service<br>yes: BOM import (scope import, type pom), a local BOM module, and a module listed only inside a <profile> |
203
+ | Maven (ear packaging) | supported | yes: an ear module packaging an ejb module and a war module |
204
+ | Maven (war packaging) | supported | yes: packaging war with src/main/webapp/WEB-INF/web.xml and no main method |
205
+ | Maven + maven-bundle-plugin (OSGi) | supported | yes: packaging bundle; one bundle exports a package, one has a Bundle-Activator |
206
+ | Maven + Quarkus | supported | yes: quarkus-maven-plugin service with no main method, plus a jar library |
207
+ | Maven Wrapper | supported | yes: mvnw, mvnw.cmd and .mvn/wrapper next to a reactor |
208
+ | sbt | partly | partly: build.sbt with project.in(file(..)), dependsOn and aggregate; Java and Scala in one module |
209
+
210
+ ## Project and folder layouts
211
+
212
+ 11 supported, 0 partly, 0 not yet.
213
+
214
+ | Name | Status | Ways of using it that were tested |
215
+ |---|---|---|
216
+ | Gradle (Groovy DSL) | supported | yes: project(':x').projectDir = file('other/folder') in settings.gradle |
217
+ | Gradle (Kotlin DSL) | supported | yes: include("services:orders") with colon paths mapping to nested folders |
218
+ | Gradle + Micronaut | supported | yes: io.micronaut.application service and io.micronaut.library library |
219
+ | Gradle + Spring Boot | supported | yes: a shared library applying the Spring Boot plugin with bootJar disabled |
220
+ | Gradle test source sets | supported | yes: src/test, src/integrationTest (jvm-test-suite), src/testFixtures, and a test-only module |
221
+ | Gradle with custom sourceSets | supported | yes: srcDirs = ['src'] and ['test'] instead of src/main/java |
222
+ | Java Platform Module System | supported | yes: module-info.java in each module (exports / requires) |
223
+ | javac + jar (no build tool) | supported | yes: flat src/ with packages, a MANIFEST.MF Main-Class and a shell script |
224
+ | Maven | supported | yes: aggregator pom in a subfolder listing ../sibling modules (flat multi-module) |
225
+ | Maven or Gradle output folders | supported | yes: target/, build/, out/ (IntelliJ), bin/ (Eclipse), .gradle/, .idea/ next to real source<br>yes: target/, build/, out/ (IntelliJ), bin/ (Eclipse), .gradle/, .idea/ next to real source, with no .gitignore |
226
+ | niro-local (way of adding a repository) | supported | yes: one `niro-local init` at the repository root; a root docker-compose.yml names each service with `build:`<br>yes: each service folder and the caller added one by one with `niro-local init --project <same>`<br>yes: each service is its own git checkout inside one parent folder; one `niro-local init` at the parent<br>yes: only the caller folder is added; the services it calls are not in the project<br>yes: one `niro-local init` at the root of a Maven reactor with no deploy descriptor |