@niroai/niro 0.17.0 → 1.0.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.
- package/CHANGELOG.md +136 -0
- package/README.md +123 -302
- package/bin/niro.js +12 -1
- package/docs/agent-antigravity.md +37 -0
- package/docs/agent-claude-code.md +48 -0
- package/docs/agent-claude-desktop.md +47 -0
- package/docs/agent-cline.md +42 -0
- package/docs/agent-codex.md +45 -0
- package/docs/agent-copilot-cli.md +42 -0
- package/docs/agent-cursor.md +44 -0
- package/docs/agent-factory.md +42 -0
- package/docs/agent-gemini-cli.md +42 -0
- package/docs/agent-goose.md +42 -0
- package/docs/agent-kiro.md +37 -0
- package/docs/agent-opencode.md +37 -0
- package/docs/agent-vscode.md +45 -0
- package/docs/agent-windsurf.md +38 -0
- package/docs/answer-shapes.md +69 -0
- package/docs/builds-and-updates.md +68 -0
- package/docs/cloud-README.md +372 -0
- package/docs/configuring-a-folder.md +51 -0
- package/docs/connect-ci.md +24 -0
- package/docs/connect-overview.md +20 -0
- package/docs/connect-review-bots.md +17 -0
- package/docs/connect-team-server.md +12 -0
- package/docs/connect-terminal.md +49 -0
- package/docs/connect-web-agents.md +9 -0
- package/docs/connect-your-ai-assistant.md +59 -175
- package/docs/coverage-audit-and-consent.md +51 -0
- package/docs/evaluate-what-niro-did.md +271 -0
- package/docs/faq-assistants-and-mcp.md +122 -0
- package/docs/faq-feedback-and-receipts.md +33 -0
- package/docs/faq-indexing.md +127 -0
- package/docs/faq-install-and-setup.md +103 -0
- package/docs/faq-licence-and-plans.md +86 -0
- package/docs/faq-login-and-account.md +69 -0
- package/docs/faq-offline.md +34 -0
- package/docs/faq-performance.md +33 -0
- package/docs/faq-privacy-and-security.md +113 -0
- package/docs/faq-uninstall.md +47 -0
- package/docs/faq-updates.md +59 -0
- package/docs/faq-worktrees-and-branches.md +59 -0
- package/docs/faq-wrong-or-missing-answers.md +275 -0
- package/docs/hosted-only.md +33 -0
- package/docs/how-the-graph-works.md +47 -0
- package/docs/index.md +157 -0
- package/docs/licence-and-plans.md +72 -0
- package/docs/lifecycle-debug.md +48 -0
- package/docs/lifecycle-onboarding.md +32 -0
- package/docs/lifecycle-overview.md +77 -0
- package/docs/lifecycle-plan-and-design.md +44 -0
- package/docs/lifecycle-review.md +30 -0
- package/docs/lifecycle-security-and-privacy.md +35 -0
- package/docs/lifecycle-test.md +28 -0
- package/docs/lifecycle-write-code.md +35 -0
- package/docs/llms-full.txt +8015 -0
- package/docs/llms.txt +126 -0
- package/docs/playbook-add-a-feature.md +108 -0
- package/docs/playbook-change-safely.md +93 -0
- package/docs/playbook-data-and-events.md +107 -0
- package/docs/playbook-debug-after-a-change.md +96 -0
- package/docs/playbook-debug-config.md +95 -0
- package/docs/playbook-debug-exception.md +124 -0
- package/docs/playbook-debug-failing-service-call.md +119 -0
- package/docs/playbook-debug-slow-path.md +80 -0
- package/docs/playbook-debug-wrong-value.md +137 -0
- package/docs/playbook-onboard.md +95 -0
- package/docs/playbook-review-a-change.md +72 -0
- package/docs/playbook-test-a-change.md +73 -0
- package/docs/reference-cli.md +113 -0
- package/docs/reference-config-files.md +42 -0
- package/docs/reference-engine-commands.md +56 -0
- package/docs/reference-environment-variables.md +89 -0
- package/docs/reference-exit-codes.md +67 -0
- package/docs/reference-limits.md +75 -0
- package/docs/reference-mcp-tools.md +326 -0
- package/docs/reference-messages.md +180 -0
- package/docs/secrets-and-masking.md +48 -0
- package/docs/supported-c.md +130 -0
- package/docs/supported-cpp.md +157 -0
- package/docs/supported-csharp.md +211 -0
- package/docs/supported-go.md +258 -0
- package/docs/supported-java.md +226 -0
- package/docs/supported-javascript.md +223 -0
- package/docs/supported-kotlin.md +124 -0
- package/docs/supported-overview.md +89 -0
- package/docs/supported-php.md +157 -0
- package/docs/supported-python.md +224 -0
- package/docs/supported-ruby.md +162 -0
- package/docs/supported-rust.md +150 -0
- package/docs/supported-swift.md +133 -0
- package/docs/supported-typescript.md +220 -0
- package/docs/tokens-speed-and-accuracy.md +99 -0
- package/docs/troubleshooting.md +42 -0
- package/docs/uninstall.md +74 -0
- package/docs/what-leaves-your-machine.md +71 -0
- package/docs/where-things-are-stored.md +59 -0
- package/docs/worktrees-and-branches.md +55 -0
- package/package.json +5 -3
- package/src/commands/add-repo.js +5 -0
- package/src/commands/auditSend.js +67 -0
- package/src/commands/build.js +6 -0
- package/src/commands/docsSend.js +73 -0
- package/src/commands/engine.js +120 -0
- package/src/commands/engineRoutes.js +105 -0
- package/src/commands/guide.js +254 -0
- package/src/commands/init.js +6 -2
- package/src/commands/initLocal.js +96 -0
- package/src/commands/journalSend.js +47 -0
- package/src/commands/login.js +89 -12
- package/src/commands/mcp.js +22 -6
- package/src/commands/plan.js +99 -0
- package/src/commands/repoPush.js +33 -0
- package/src/commands/requestIntegration.js +38 -0
- package/src/commands/share.js +56 -0
- package/src/commands/start.js +451 -371
- package/src/commands/status.js +57 -0
- package/src/commands/takeover.js +6 -0
- package/src/commands/uninstall.js +180 -0
- package/src/commands/upgrade.js +38 -8
- package/src/commands/watch.js +420 -6
- package/src/index.js +174 -3
- package/src/lib/agentApi.js +32 -1
- package/src/lib/api.js +20 -6
- package/src/lib/auditUpload.js +293 -0
- package/src/lib/branchDrift.js +149 -0
- package/src/lib/choose.js +116 -0
- package/src/lib/cloudGuard.js +74 -0
- package/src/lib/credentials.js +2 -2
- package/src/lib/docsMarked.js +55 -0
- package/src/lib/docsState.js +213 -0
- package/src/lib/docsUpload.js +481 -0
- package/src/lib/engine.js +619 -0
- package/src/lib/folderSync.js +2 -1
- package/src/lib/graphCheck.js +40 -0
- package/src/lib/guide.js +293 -0
- package/src/lib/guideSearch.js +252 -0
- package/src/lib/integrationRequest.js +89 -0
- package/src/lib/journalUpload.js +147 -0
- package/src/lib/languages.js +129 -0
- package/src/lib/lease.js +375 -0
- package/src/lib/localBuild.js +285 -0
- package/src/lib/localEngine.js +210 -0
- package/src/lib/localOnboard.js +124 -0
- package/src/lib/localWorktrees.js +243 -0
- package/src/lib/machineCheck.js +58 -0
- package/src/lib/mcpClients.js +10 -1
- package/src/lib/migrationNotice.js +118 -0
- package/src/lib/modelFetch.js +153 -0
- package/src/lib/nestedOutput.js +23 -9
- package/src/lib/onboardingLog.js +34 -0
- package/src/lib/planUsage.js +165 -0
- package/src/lib/progressBar.js +46 -0
- package/src/lib/prompt.js +1 -1
- package/src/lib/redact.js +155 -0
- package/src/lib/release.js +33 -0
- package/src/lib/repoPush.js +495 -0
- package/src/lib/secret.js +1 -1
- package/src/lib/service.js +372 -63
- package/src/lib/shareCode.js +367 -0
- package/src/lib/shareExclusions.js +114 -0
- package/src/lib/shareFiles.js +129 -0
- package/src/lib/spinner.js +9 -5
- package/src/lib/watchDaemon.js +33 -10
- package/src/lib/watchState.js +12 -1
- package/src/lib/windowsPaths.js +67 -0
- package/src/mcp/lineCheck.js +382 -0
- package/src/mcp/lineName.js +92 -0
- package/src/mcp/localBackend.js +751 -0
- package/src/mcp/localMode.js +383 -0
- package/src/mcp/localSkill.js +189 -0
- package/src/mcp/server.js +610 -79
- package/src/mcp/setup.js +519 -131
- package/src/mcp/shellSearchHook.js +509 -0
- package/src/mcp/teardown.js +173 -91
- package/src/mcp/usingNiro.js +39 -0
- package/docs/working-on-branches.md +0 -162
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# Supported in C
|
|
2
|
+
|
|
3
|
+
<!-- GENERATED by scripts/gen-supported-docs.js. Do not edit by hand: run the script again. -->
|
|
4
|
+
<!-- source: catalog/c.json; catalog/c.structure.json -->
|
|
5
|
+
<!-- measured: coverage corpus 1bb4ebb, niro-local 2b30d4fd -->
|
|
6
|
+
|
|
7
|
+
This page lists the C 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
|
+
## Web frameworks and HTTP servers (the routes your code serves)
|
|
19
|
+
|
|
20
|
+
0 supported, 0 partly, 10 not yet.
|
|
21
|
+
|
|
22
|
+
| Name | Status | Ways of using it that were tested |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| Cesanta mongoose | not yet | no: mg_http_listen + handler that matches hm->uri with mg_match<br>no: mg_http_match_uri(hm, path) (mongoose 7.0 to 7.13) |
|
|
25
|
+
| civetweb (C API) | not yet | no: mg_set_request_handler(ctx, path, handler, cbdata)<br>no: mg_set_websocket_handler(ctx, path, ...)<br>no: mg_set_auth_handler(ctx, path, handler, cbdata) |
|
|
26
|
+
| facil.io | not yet | no: http_listen with one on_request; path compared inside |
|
|
27
|
+
| GNU libmicrohttpd | not yet | no: one MHD_AccessHandlerCallback; url and method compared inside it |
|
|
28
|
+
| Kore | not yet | no: routes declared in kore.conf (`route /path handler`) |
|
|
29
|
+
| libevent evhttp | not yet | no: evhttp_set_cb(http, path, cb, arg) |
|
|
30
|
+
| libh2o | not yet | no: h2o_config_register_path(hostconf, path, flags) + handler |
|
|
31
|
+
| libsoup (GNOME) | not yet | no: soup_server_add_handler(server, path, cb, data, destroy) |
|
|
32
|
+
| Lwan | not yet | no: lwan_url_map array of {.prefix, .handler} |
|
|
33
|
+
| Ulfius | not yet | no: ulfius_add_endpoint_by_val(inst, verb, prefix, template, priority, cb, data) |
|
|
34
|
+
|
|
35
|
+
## The language's own HTTP server
|
|
36
|
+
|
|
37
|
+
0 supported, 0 partly, 1 not yet.
|
|
38
|
+
|
|
39
|
+
| Name | Status | Ways of using it that were tested |
|
|
40
|
+
|---|---|---|
|
|
41
|
+
| POSIX sockets (no library) | not yet | no: socket/bind/listen/accept, request line read with sscanf, path compared with strcmp |
|
|
42
|
+
|
|
43
|
+
## HTTP client libraries (the calls your code makes to other services)
|
|
44
|
+
|
|
45
|
+
0 supported, 0 partly, 6 not yet.
|
|
46
|
+
|
|
47
|
+
| Name | Status | Ways of using it that were tested |
|
|
48
|
+
|---|---|---|
|
|
49
|
+
| Cesanta mongoose | not yet | no: mg_http_connect(mgr, url, fn, data); request written in fn |
|
|
50
|
+
| civetweb (C API) | not yet | no: mg_download(host, port, ssl, ebuf, len, request line) |
|
|
51
|
+
| libcurl | not yet | no: curl_easy_setopt(h, CURLOPT_URL, literal) then curl_easy_perform<br>no: CURLOPT_URL then CURLOPT_POSTFIELDS (verb is POST)<br>no: CURLOPT_CUSTOMREQUEST names the verb<br>no: base URL from getenv, path appended with snprintf<br>no: curl_url_set(h, CURLUPART_URL, literal) + CURLOPT_CURLU<br>no: easy handle with URL added to a multi handle<br>no: URL in a #define used as the option value |
|
|
52
|
+
| libevent evhttp | not yet | no: evhttp_connection_base_new(base, dns, host, port) + evhttp_make_request(conn, req, verb, path) |
|
|
53
|
+
| libsoup (GNOME) | not yet | no: soup_message_new(verb, url) + soup_session_send_and_read |
|
|
54
|
+
| neon | not yet | no: ne_session_create(scheme, host, port) + ne_request_create(sess, verb, path) |
|
|
55
|
+
|
|
56
|
+
## The language's own HTTP client
|
|
57
|
+
|
|
58
|
+
0 supported, 0 partly, 1 not yet.
|
|
59
|
+
|
|
60
|
+
| Name | Status | Ways of using it that were tested |
|
|
61
|
+
|---|---|---|
|
|
62
|
+
| POSIX sockets (no library) | not yet | no: getaddrinfo + connect + send of a hand-written request line |
|
|
63
|
+
|
|
64
|
+
## gRPC
|
|
65
|
+
|
|
66
|
+
0 supported, 0 partly, 1 not yet.
|
|
67
|
+
|
|
68
|
+
| Name | Status | Ways of using it that were tested |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| gRPC core C API | not yet | no: grpc_channel_create + grpc_channel_create_call with a method slice |
|
|
71
|
+
|
|
72
|
+
## Databases and data stores
|
|
73
|
+
|
|
74
|
+
0 supported, 4 partly, 4 not yet.
|
|
75
|
+
|
|
76
|
+
| Name | Status | Ways of using it that were tested |
|
|
77
|
+
|---|---|---|
|
|
78
|
+
| hiredis | partly | yes: redisCommand(ctx, "VERB key ...", args)<br>no: redisCommandArgv(ctx, argc, argv, lens)<br>no: redisAppendCommand (pipelining) + redisGetReply |
|
|
79
|
+
| libmemcached | not yet | no: memcached_set / memcached_get / memcached_delete with a key |
|
|
80
|
+
| libmysqlclient / MariaDB Connector/C | partly | no: mysql_real_connect(conn, host, user, pw, db, port, ...)<br>yes: mysql_query(conn, sql)<br>yes: mysql_real_query(conn, sql_variable, len)<br>no: mysql_stmt_prepare(stmt, sql, len) + mysql_stmt_execute |
|
|
81
|
+
| libpq | partly | no: PQconnectdb with a URI or key=value connection string<br>partly: PQexec(conn, sql)<br>yes: PQexecParams(conn, sql, n, types, values, ...)<br>yes: PQprepare(conn, name, sql, ...) then PQexecPrepared(conn, name, ...)<br>no: PQsendQuery / PQsendQueryParams (asynchronous) |
|
|
82
|
+
| LMDB / Berkeley DB | not yet | no: embedded key-value stores (mdb_put, db->put) |
|
|
83
|
+
| MongoDB C driver (libmongoc) | not yet | no: mongoc_client_get_collection(client, db, name) + insert_one / find_with_opts / update_one / delete_one<br>no: mongoc_database_get_collection(db, name) |
|
|
84
|
+
| ODBC (unixODBC / Windows driver manager) | not yet | no: SQLExecDirect(stmt, sql, SQL_NTS) and SQLPrepare + SQLExecute |
|
|
85
|
+
| SQLite C API | partly | yes: sqlite3_exec(db, sql, cb, arg, err)<br>no: sqlite3_prepare_v2(db, SQL_CONSTANT, -1, &stmt, NULL)<br>no: sqlite3_prepare_v3 (and sqlite3_prepare16_v2) |
|
|
86
|
+
|
|
87
|
+
## Messaging and events (queues, topics, streams)
|
|
88
|
+
|
|
89
|
+
1 supported, 0 partly, 11 not yet.
|
|
90
|
+
|
|
91
|
+
| Name | Status | Ways of using it that were tested |
|
|
92
|
+
|---|---|---|
|
|
93
|
+
| CZMQ | not yet | no: zsock_new_pub("@tcp://...") / zsock_new_sub(">tcp://...", prefix) |
|
|
94
|
+
| D-Bus (libdbus / sd-bus) | not yet | no: dbus_message_new_signal(path, iface, name) / sd_bus_emit_signal |
|
|
95
|
+
| Eclipse Paho MQTT C | not yet | no: MQTTClient_publishMessage(client, topic, &msg, &token)<br>no: MQTTClient_publish(client, topic, len, payload, qos, retained, &token)<br>no: MQTTClient_subscribe(client, topic, qos)<br>no: MQTTAsync_sendMessage / MQTTAsync_subscribe |
|
|
96
|
+
| hiredis | not yet | no: redisCommand(ctx, "PUBLISH channel %s", payload)<br>no: redisAsyncCommand(ac, cb, data, "SUBSCRIBE channel") |
|
|
97
|
+
| libmosquitto | supported | yes: mosquitto_publish(mosq, mid, topic, len, payload, qos, retain)<br>yes: mosquitto_subscribe(mosq, mid, topic, qos) |
|
|
98
|
+
| libpq | not yet | no: PQexec(conn, "LISTEN ch") / "NOTIFY ch" (PostgreSQL pub-sub) |
|
|
99
|
+
| librdkafka (C API) | not yet | no: rd_kafka_topic_new(rk, name, conf) then rd_kafka_produce(rkt, ...)<br>no: rd_kafka_producev(rk, RD_KAFKA_V_TOPIC(name), ...)<br>no: rd_kafka_topic_partition_list_add(list, name, part) + rd_kafka_subscribe |
|
|
100
|
+
| nanomsg | not yet | no: nn_socket(AF_SP, NN_PUB) + nn_bind + nn_send; nn_connect for SUB |
|
|
101
|
+
| NATS C client (cnats) | not yet | no: natsConnection_PublishString(nc, subject, data)<br>no: natsConnection_Subscribe(&sub, nc, subject, cb, closure)<br>no: natsConnection_RequestString(&reply, nc, subject, data, timeout) |
|
|
102
|
+
| nng | not yet | no: nng_pub0_open + nng_listen; nng_sub0_open + NNG_OPT_SUB_SUBSCRIBE + nng_dial |
|
|
103
|
+
| rabbitmq-c (librabbitmq) | not yet | no: amqp_basic_publish(conn, ch, exchange, routing_key, ...)<br>no: amqp_queue_declare + amqp_basic_consume(conn, ch, queue, ...) |
|
|
104
|
+
| ZeroMQ (libzmq) | not yet | no: zmq_socket(ctx, ZMQ_PUB) + zmq_bind(addr) + zmq_send<br>no: zmq_connect(addr) + zmq_setsockopt(ZMQ_SUBSCRIBE, prefix)<br>no: ZMQ_REP bound socket answering ZMQ_REQ peers |
|
|
105
|
+
|
|
106
|
+
## Build tools and package managers
|
|
107
|
+
|
|
108
|
+
7 supported, 0 partly, 0 not yet.
|
|
109
|
+
|
|
110
|
+
| Name | Status | Ways of using it that were tested |
|
|
111
|
+
|---|---|---|
|
|
112
|
+
| CMake (C project) | supported | yes: root project() + add_subdirectory per library and service; target_link_libraries |
|
|
113
|
+
| GNU Autotools | supported | yes: configure.ac + Makefile.am per folder: bin_PROGRAMS, lib_LTLIBRARIES, check_PROGRAMS |
|
|
114
|
+
| GNU Make | supported | yes: one Makefile at the root, sources in src/, one binary |
|
|
115
|
+
| GNU Make (recursive) | supported | yes: top Makefile with SUBDIRS and $(MAKE) -C, one Makefile per folder |
|
|
116
|
+
| Meson | supported | yes: meson.build with subdir(); executable(), static_library(), declare_dependency(), test() |
|
|
117
|
+
| PlatformIO | supported | yes: platformio.ini with src/, lib/<name>/, test/, and .pio/ output |
|
|
118
|
+
| SCons | supported | yes: SConstruct + SConscript per folder; Program() and StaticLibrary() |
|
|
119
|
+
|
|
120
|
+
## Project and folder layouts
|
|
121
|
+
|
|
122
|
+
5 supported, 0 partly, 0 not yet.
|
|
123
|
+
|
|
124
|
+
| Name | Status | Ways of using it that were tested |
|
|
125
|
+
|---|---|---|
|
|
126
|
+
| Bison and Flex output checked in | supported | yes: gen/parser.tab.c and gen/lexer.c next to the .y grammar |
|
|
127
|
+
| CMake (include/ + src/ + apps/ + tests/) | supported | yes: public headers in include/<name>/, sources in src/, one root CMakeLists |
|
|
128
|
+
| CMake build folders and vendored copies | supported | yes: build/ and cmake-build-debug/ (CLion) output; third_party/ and deps/ vendored libraries |
|
|
129
|
+
| GNU Make + tests/ with its own Makefile | supported | yes: a test folder whose Makefile builds a test binary with a main |
|
|
130
|
+
| no build tool (shell script) | supported | yes: flat folder of .c files compiled by build.sh |
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
# Supported in C++
|
|
2
|
+
|
|
3
|
+
<!-- GENERATED by scripts/gen-supported-docs.js. Do not edit by hand: run the script again. -->
|
|
4
|
+
<!-- source: catalog/cpp.json; catalog/cpp.structure.json -->
|
|
5
|
+
<!-- measured: coverage corpus 1bb4ebb, niro-local 2b30d4fd -->
|
|
6
|
+
|
|
7
|
+
This page lists the C++ 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
|
+
## Web frameworks and HTTP servers (the routes your code serves)
|
|
19
|
+
|
|
20
|
+
3 supported, 2 partly, 10 not yet.
|
|
21
|
+
|
|
22
|
+
| Name | Status | Ways of using it that were tested |
|
|
23
|
+
|---|---|---|
|
|
24
|
+
| Boost.Beast | not yet | no: one handler comparing req.method() and req.target() |
|
|
25
|
+
| civetweb C++ (CivetServer) | not yet | no: server.addHandler(path, handler) with CivetHandler::handleGet/handlePost |
|
|
26
|
+
| cpp-httplib | supported | yes: svr.Get(path, lambda)<br>yes: svr.Post(path, named_function)<br>yes: regex path in a raw string literal<br>yes: path parameter written :id (cpp-httplib 0.10+) |
|
|
27
|
+
| cpprestsdk (Casablanca) | not yet | no: http_listener(U("http://host:port/path")) + listener.support(methods::GET, h) |
|
|
28
|
+
| Crow | supported | yes: CROW_ROUTE(app, path)(handler), GET by default<br>yes: .methods("POST"_method)<br>yes: .methods(crow::HTTPMethod::Delete)<br>yes: crow::Blueprint bp(prefix) + CROW_BP_ROUTE(bp, path)<br>yes: CROW_WEBSOCKET_ROUTE(app, path)<br>yes: CROW_CATCHALL_ROUTE(app)<br>yes: app.route_dynamic(path)(handler) |
|
|
29
|
+
| Drogon | partly | yes: app().registerHandler(path, handler, {Get})<br>yes: registerHandler(path, handler, {drogon::Post, drogon::Put})<br>no: HttpController<T> with METHOD_LIST_BEGIN, ADD_METHOD_TO (absolute) and METHOD_ADD (relative to /ns/Class)<br>no: HttpSimpleController<T> with PATH_ADD(path, verbs)<br>partly: WebSocketController<T> with WS_PATH_ADD(path) |
|
|
30
|
+
| Oat++ | not yet | no: ENDPOINT("VERB", "/path", name, params...) inside an ApiController |
|
|
31
|
+
| Pistache | supported | yes: Routes::Get(router, path, Routes::bind(&C::m, this)) |
|
|
32
|
+
| POCO Net | not yet | no: HTTPRequestHandlerFactory::createRequestHandler comparing request.getURI() |
|
|
33
|
+
| Qt HTTP Server | not yet | no: QHttpServer::route(path, QHttpServerRequest::Method::X, h) |
|
|
34
|
+
| RESTinio | not yet | no: router->http_get(path, h), http_post, http_put, http_delete |
|
|
35
|
+
| Seastar httpd | not yet | no: routes.add(operation_type::GET, url("/x"), handler) |
|
|
36
|
+
| userver | not yet | no: HttpHandlerBase subclass; path in static_config.yaml (`path: /v1/orders`) |
|
|
37
|
+
| uWebSockets | partly | partly: uWS::App().get(path, h).post(...).del(...).ws<T>(path, ...) |
|
|
38
|
+
| Wt | not yet | no: WServer::addResource(&resource, path) |
|
|
39
|
+
|
|
40
|
+
## The language's own HTTP server
|
|
41
|
+
|
|
42
|
+
0 supported, 0 partly, 2 not yet.
|
|
43
|
+
|
|
44
|
+
| Name | Status | Ways of using it that were tested |
|
|
45
|
+
|---|---|---|
|
|
46
|
+
| Boost.Asio (raw TCP) | not yet | no: acceptor + read_until("\r\n\r\n") + hand-parsed request line |
|
|
47
|
+
| POSIX sockets (no library) | not yet | no: accept + recv, request line split with istringstream, compared with == |
|
|
48
|
+
|
|
49
|
+
## HTTP client libraries (the calls your code makes to other services)
|
|
50
|
+
|
|
51
|
+
1 supported, 0 partly, 10 not yet.
|
|
52
|
+
|
|
53
|
+
| Name | Status | Ways of using it that were tested |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| Boost.Beast | not yet | no: resolver.resolve(host, port) + http::request<...>{http::verb::get, target, 11} |
|
|
56
|
+
| cpp-httplib | not yet | no: httplib::Client cli(base or host, port); cli.Get(path), Post, Delete |
|
|
57
|
+
| cpprestsdk (Casablanca) | not yet | no: http_client(U(base)).request(methods::GET, U(path)) |
|
|
58
|
+
| cpr | not yet | no: cpr::Get(cpr::Url{literal})<br>no: cpr::Post(cpr::Url{...}, cpr::Body{...}, cpr::Header{...})<br>no: cpr::Session; session.SetUrl(cpr::Url{...}); session.Get()<br>no: cpr::Url{std::string(std::getenv("X")) + "/path"} |
|
|
59
|
+
| curlpp / cpp-netlib | not yet | no: curlpp::options::Url(url); boost::network::http::client::request(url) |
|
|
60
|
+
| Drogon | not yet | no: HttpClient::newHttpClient(base); req->setPath(p); req->setMethod(drogon::Get); client->sendRequest(req) |
|
|
61
|
+
| libcurl | not yet | no: curl_easy_setopt(h, CURLOPT_URL, literal) from C++ |
|
|
62
|
+
| Oat++ | not yet | no: ApiClient with API_CALL("VERB", "/path", name) |
|
|
63
|
+
| POCO Net | not yet | no: HTTPClientSession(host, port) + HTTPRequest(HTTP_GET, path) + sendRequest |
|
|
64
|
+
| Qt Network | not yet | no: QNetworkAccessManager::get / post / deleteResource(QNetworkRequest(QUrl(url))) |
|
|
65
|
+
| restclient-cpp | supported | yes: RestClient::get(url), post(url, type, body) |
|
|
66
|
+
|
|
67
|
+
## The language's own HTTP client
|
|
68
|
+
|
|
69
|
+
0 supported, 0 partly, 2 not yet.
|
|
70
|
+
|
|
71
|
+
| Name | Status | Ways of using it that were tested |
|
|
72
|
+
|---|---|---|
|
|
73
|
+
| POSIX sockets (no library) | not yet | no: getaddrinfo + connect + send of a request line |
|
|
74
|
+
| WinHTTP (Windows built-in) | not yet | no: WinHttpConnect(session, host, port) + WinHttpOpenRequest(conn, verb, path) |
|
|
75
|
+
|
|
76
|
+
## gRPC
|
|
77
|
+
|
|
78
|
+
0 supported, 1 partly, 1 not yet.
|
|
79
|
+
|
|
80
|
+
| Name | Status | Ways of using it that were tested |
|
|
81
|
+
|---|---|---|
|
|
82
|
+
| Apache bRPC | not yet | no: protobuf service implemented by a class, server.AddService(&impl, ...) |
|
|
83
|
+
| gRPC C++ | partly | yes: class X : public pkg::S::Service with override methods (grpc-plan.md section 3 (cpp row) and 8.1)<br>yes: override taking ServerWriter<T>* / ServerReader<T>* / ServerReaderWriter<A,B>*<br>yes: S::AsyncService member; service_.RequestM(&ctx, &req, &responder, cq, cq, tag)<br>yes: class X : public S::CallbackService with reactor overrides (incl. bidi)<br>partly: auto stub = S::NewStub(channel); stub->M(&ctx, req, &reply)<br>yes: stub->AsyncM(...) and stub->PrepareAsyncM(...) (prefix stripped)<br>yes: stub->async()->M(&ctx, &req, &reply, callback)<br>yes: std::unique_ptr<ClientReader<T>> reader(stub->M(&ctx, req))<br>yes: grpc::CreateChannel(std::getenv("X"), creds) feeding NewStub<br>yes: grpc::GenericStub::PrepareUnaryCall(&ctx, "/pkg.S/M", buf, &cq)<br>no: AsyncGenericService / CallbackGenericService (method chosen at run time) |
|
|
84
|
+
|
|
85
|
+
## Databases and data stores
|
|
86
|
+
|
|
87
|
+
0 supported, 1 partly, 14 not yet.
|
|
88
|
+
|
|
89
|
+
| Name | Status | Ways of using it that were tested |
|
|
90
|
+
|---|---|---|
|
|
91
|
+
| AWS SDK for C++ (DynamoDB) | not yet | no: PutItemRequest req; req.SetTableName(name); client.PutItem(req) |
|
|
92
|
+
| DataStax C/C++ driver (Cassandra, ScyllaDB) | not yet | no: cass_statement_new(cql, n) + cass_session_execute |
|
|
93
|
+
| Drogon ORM | not yet | no: db->execSqlAsync(sql, ok, err, args...)<br>no: db->execSqlSync(sql, args...)<br>no: orm::Mapper<Model>(db).findAll() (table from the generated model) |
|
|
94
|
+
| hiredis (from C++) | not yet | no: redisCommand(ctx.get(), "SET key %s", ...) in a .cpp file |
|
|
95
|
+
| libpqxx | partly | partly: tx.exec(sql)<br>no: tx.exec_params(sql, args...)<br>no: tx.query<T...>(sql) (libpqxx 7.8+)<br>yes: tx.query_value<T>(sql)<br>yes: tx.query1<T>(sql)<br>no: c.prepare(name, sql) then tx.exec_prepared(name, args)<br>no: pqxx::connection c{uri} |
|
|
96
|
+
| MongoDB C++ driver (mongocxx) | not yet | no: db.collection(name).insert_one / find_one<br>no: auto coll = db["ratings"]; coll.update_one(...)<br>no: collection(name).aggregate(pipeline) |
|
|
97
|
+
| MySQL Connector/C++ (JDBC API) | not yet | no: stmt->executeQuery(sql)<br>no: con->prepareStatement(sql) + executeUpdate<br>no: stmt->execute(sql) |
|
|
98
|
+
| MySQL Connector/C++ (X DevAPI) | not yet | no: sess.getSchema(db).getTable(name).select(...) / getCollection(name).add(...) |
|
|
99
|
+
| ODB / sqlpp11 | not yet | no: typed ORMs (db->persist(obj), select(...).from(tab)) |
|
|
100
|
+
| POCO Data | not yet | no: session << "SQL", into(x), use(y), now |
|
|
101
|
+
| Qt SQL | not yet | no: QSqlQuery::exec(sql) and prepare(sql) + exec() |
|
|
102
|
+
| redis-plus-plus | not yet | no: redis.set(key, v), get(key), del(key)<br>no: redis.hset(key, field, v), hget(key, field)<br>no: redis.command<T>("VERB", key, ...) |
|
|
103
|
+
| SOCI | not yet | no: sql << "SELECT ...", soci::use(x), soci::into(y)<br>no: soci::statement st = (sql.prepare << "...", use(...)); st.execute(true)<br>no: soci::rowset<soci::row> rs = (sql.prepare << "SELECT ...") |
|
|
104
|
+
| sqlite_orm | not yet | no: make_storage(file, make_table(name, columns...)); storage.get_all<T>() |
|
|
105
|
+
| SQLiteC++ | not yet | no: SQLite::Database::exec(sql)<br>no: SQLite::Statement query(db, sql) |
|
|
106
|
+
|
|
107
|
+
## Messaging and events (queues, topics, streams)
|
|
108
|
+
|
|
109
|
+
0 supported, 0 partly, 9 not yet.
|
|
110
|
+
|
|
111
|
+
| Name | Status | Ways of using it that were tested |
|
|
112
|
+
|---|---|---|
|
|
113
|
+
| AMQP-CPP (Copernica) | not yet | no: channel.publish(exchange, routing_key, body)<br>no: channel.consume(queue).onReceived(cb)<br>no: declareExchange / declareQueue / bindQueue(exchange, queue, key) |
|
|
114
|
+
| AWS SDK for C++ (SQS) | not yet | no: SendMessageRequest.SetQueueUrl(url) + sqs.SendMessage; ReceiveMessageRequest |
|
|
115
|
+
| cppkafka | not yet | no: producer.produce(MessageBuilder(topic).partition(p).payload(x))<br>no: BufferedProducer.add_message(make_builder(topic)...)<br>no: consumer.subscribe({topics}); consumer.poll() |
|
|
116
|
+
| cppzmq | not yet | no: zmq::socket_t s(ctx, zmq::socket_type::pub); s.bind(addr); s.send(...)<br>no: s.connect(addr); s.set(zmq::sockopt::subscribe, prefix)<br>no: zmq::socket_type::rep bound; recv then send |
|
|
117
|
+
| Eclipse Paho MQTT C++ | not yet | no: cli.publish(topic, payload, qos, retained)<br>no: mqtt::make_message(topic, payload) then cli.publish(msg)<br>no: cli.subscribe(topic, qos); consume_message()<br>no: mqtt::topic t(cli, name, qos); t.publish(payload)<br>no: mqtt::client (synchronous) publish(make_message(...)) |
|
|
118
|
+
| librdkafka C++ API | not yet | no: producer->produce(topic_name, partition, flags, payload, len, ...)<br>no: RdKafka::Topic::create(producer, name, conf, err) then produce(topic, ...)<br>no: KafkaConsumer::create + consumer->subscribe({topics}) |
|
|
119
|
+
| NATS C client (from C++) | not yet | no: natsConnection_PublishString / Subscribe called from C++ |
|
|
120
|
+
| redis-plus-plus | not yet | no: redis.publish(channel, message)<br>no: auto sub = redis.subscriber(); sub.subscribe(channel); sub.consume() |
|
|
121
|
+
| SimpleAmqpClient | not yet | no: ch->BasicPublish(exchange, routing_key, BasicMessage::Create(body))<br>no: ch->DeclareQueue(q); ch->BasicConsume(q); BasicConsumeMessage(tag) |
|
|
122
|
+
|
|
123
|
+
## Build tools and package managers
|
|
124
|
+
|
|
125
|
+
14 supported, 0 partly, 0 not yet.
|
|
126
|
+
|
|
127
|
+
| Name | Status | Ways of using it that were tested |
|
|
128
|
+
|---|---|---|
|
|
129
|
+
| Bazel (Bzlmod) | supported | yes: MODULE.bazel + BUILD.bazel with cc_binary / cc_library / cc_test; bazel-out and bazel-bin output |
|
|
130
|
+
| Bazel (WORKSPACE) | supported | yes: WORKSPACE + BUILD files (pre-Bzlmod) |
|
|
131
|
+
| CMake | supported | yes: root aggregator + add_subdirectory; add_library and two add_executable; target_link_libraries |
|
|
132
|
+
| CMake FetchContent | supported | yes: FetchContent_Declare + MakeAvailable; fetched sources under build/_deps |
|
|
133
|
+
| CMake presets | supported | yes: CMakePresets.json with binaryDir out/build/<preset> (Visual Studio and VS Code default) |
|
|
134
|
+
| Conan (conanfile.txt) | supported | yes: conanfile.txt [requires] / [generators] over a CMake tree |
|
|
135
|
+
| Conan 2 (conanfile.py) | supported | yes: conanfile.py with cmake_layout over a CMake tree; generators under build/<cfg>/generators |
|
|
136
|
+
| GN + Ninja | supported | yes: BUILD.gn with executable() / static_library(); .gn root; out/<dir> output |
|
|
137
|
+
| Meson with wraps | supported | yes: meson.build subdir() tree; subprojects/*.wrap and downloaded sources; builddir/ |
|
|
138
|
+
| MSBuild (Visual Studio .sln + .vcxproj) | supported | yes: .sln listing .vcxproj files; ConfigurationType Application / StaticLibrary; ProjectReference; x64/Release output |
|
|
139
|
+
| Premake 5 | supported | yes: one premake5.lua at the root with project blocks, kind ConsoleApp / StaticLib |
|
|
140
|
+
| qmake (Qt) | supported | yes: TEMPLATE = subdirs root, TEMPLATE = app and TEMPLATE = lib .pro files |
|
|
141
|
+
| vcpkg manifest mode | supported | yes: vcpkg.json + vcpkg-configuration.json; packages installed in vcpkg_installed/ |
|
|
142
|
+
| xmake | supported | yes: xmake.lua with target(), set_kind("binary" \| "static" \| "shared"), add_deps |
|
|
143
|
+
|
|
144
|
+
## Project and folder layouts
|
|
145
|
+
|
|
146
|
+
6 supported, 2 partly, 0 not yet.
|
|
147
|
+
|
|
148
|
+
| Name | Status | Ways of using it that were tested |
|
|
149
|
+
|---|---|---|
|
|
150
|
+
| C library + C++ service (extern "C") | supported | yes: a .c library with an extern "C" guarded header called from .cpp |
|
|
151
|
+
| CMake | partly | yes: aggregators two levels deep: services/orders/{core,api}, libs/pricing<br>yes: one root CMakeLists declaring a library and two executables over src/<target>/<br>yes: examples/ and benchmarks/ executables declared EXCLUDE_FROM_ALL<br>yes: add_executable(... IMPORTED) for a tool, add_library(Shop::pricing ALIAS pricing)<br>yes: add_library(x INTERFACE) header-only and add_library(y OBJECT)<br>partly: two programs whose main functions are byte-identical, no namespace |
|
|
152
|
+
| CMake + GoogleTest / Catch2 | supported | yes: test folders whose add_executable is registered with gtest_discover_tests or add_test |
|
|
153
|
+
| header-only library | supported | yes: a library with only include/<name>/*.hpp and an INTERFACE target |
|
|
154
|
+
| include/ + src/ + apps/ (Pitchfork-style) | supported | yes: public headers include/<proj>/, implementation src/, binaries apps/<name>/ |
|
|
155
|
+
| native addon inside a Node package (node-gyp / cmake-js) | supported | yes: binding.gyp and a CMakeLists under a package.json |
|
|
156
|
+
| protoc output checked in | partly | partly: proto/gen/*.pb.cc, *.grpc.pb.cc next to the .proto files |
|
|
157
|
+
| vendored and submodule dependencies | supported | yes: third_party/, external/ (git submodule), extern/ copies of public libraries |
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# Supported in C#
|
|
2
|
+
|
|
3
|
+
<!-- GENERATED by scripts/gen-supported-docs.js. Do not edit by hand: run the script again. -->
|
|
4
|
+
<!-- source: catalog/csharp.json; catalog/csharp.structure.json -->
|
|
5
|
+
<!-- measured: coverage corpus 1bb4ebb, niro-local 2b30d4fd -->
|
|
6
|
+
|
|
7
|
+
This page lists the C# 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 3 look-alike cases for C#: 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/csharp.json and catalog/csharp.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
|
+
10 supported, 3 partly, 2 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 dotnet8, Handler Assembly::Namespace.Class::Method) with Events Type HttpApi Path and Method |
|
|
28
|
+
| Azure Functions (.NET isolated worker) | supported | yes: host.json extensions.http.routePrefix set to a value other than api (here a two-segment prefix), with a verb-less [HttpTrigger] that serves every verb |
|
|
29
|
+
| Carter | supported | yes: ICarterModule.AddRoutes(app) with app.MapGet/MapPost<br>yes: CarterModule base("/api/ratings") constructor prefix |
|
|
30
|
+
| CoreWCF | not yet | no: [ServiceContract]/[OperationContract] served at AddServiceEndpoint<,>(binding, "/X.svc") |
|
|
31
|
+
| Dapr.AspNetCore | supported | yes: [HttpPost("x")] controller action reached by Dapr invocation or pub/sub |
|
|
32
|
+
| FastEndpoints | not yet | no: Get("/x") / Post("/x") inside Configure(), plus UseFastEndpoints RoutePrefix<br>no: [HttpGet("/x")] on the endpoint class |
|
|
33
|
+
| HotChocolate.AspNetCore | supported | yes: app.MapGraphQL("/graphql") with Query/Mutation types |
|
|
34
|
+
| Microsoft.AspNet.WebApi (System.Web.Http) | partly | yes: [RoutePrefix] + [Route("{id:int}")] + [HttpGet] on ApiController (.NET Framework)<br>no: config.Routes.MapHttpRoute("DefaultApi", "api/{controller}/{id}") |
|
|
35
|
+
| Microsoft.Azure.Functions.Worker | supported | yes: [Function] + [HttpTrigger(level, "get", Route = "x/{id}")] parameter; host.json routePrefix |
|
|
36
|
+
| Microsoft.Azure.WebJobs | supported | yes: [FunctionName] + [HttpTrigger] in the in-process model |
|
|
37
|
+
| Nancy | supported | yes: NancyModule base path + Get("/x", handler) in the constructor |
|
|
38
|
+
| Ocelot | partly | partly: ocelot.json Routes: UpstreamPathTemplate -> DownstreamHostAndPorts + DownstreamPathTemplate |
|
|
39
|
+
| Serverless Framework serverless.yml | supported | yes: functions.<name>.handler Assembly::Namespace.Class::Method with events httpApi |
|
|
40
|
+
| ServiceStack | supported | yes: [Route("/x/{Id}", "GET")] on the request DTO, served by Service.Get(Dto) |
|
|
41
|
+
| Yarp.ReverseProxy | partly | partly: appsettings ReverseProxy Routes/Clusters (Match.Path -> Destinations.Address) |
|
|
42
|
+
|
|
43
|
+
## The language's own HTTP server
|
|
44
|
+
|
|
45
|
+
2 supported, 3 partly, 2 not yet.
|
|
46
|
+
|
|
47
|
+
| Name | Status | Ways of using it that were tested |
|
|
48
|
+
|---|---|---|
|
|
49
|
+
| Microsoft.AspNetCore.Builder | supported | yes: app.MapGet/MapPost/MapPut/MapDelete/MapPatch(path, lambda) in top-level Program.cs<br>yes: MapGet(path, Handlers.Method) with a method group handler<br>yes: MapMethods(path, new[]{"POST","PUT"}, handler)<br>yes: var g = app.MapGroup("/api/coupons"); g.MapGet("/", ...)<br>yes: routes registered in an IEndpointRouteBuilder extension method in another file |
|
|
50
|
+
| Microsoft.AspNetCore.Http | not yet | no: app.Run(async ctx => { if (ctx.Request.Path == "/x") ... }) terminal middleware |
|
|
51
|
+
| Microsoft.AspNetCore.Mvc | partly | yes: [Route] on the controller class + [HttpGet("{id}")] etc. on actions<br>yes: [Route("api/[controller]")] token replaced by the class name minus Controller<br>no: [AcceptVerbs("GET","HEAD", Route = "...")] naming several verbs<br>yes: [Route("~/...")] on an action, which replaces the class route<br>partly: MapControllerRoute("default", "{controller=Home}/{action=Index}/{id?}") with attribute-less controllers |
|
|
52
|
+
| Microsoft.AspNetCore.Mvc.RazorPages | partly | partly: @page "/basket/{id}" in .cshtml with OnGet/OnPost handlers |
|
|
53
|
+
| Microsoft.AspNetCore.Routing | supported | yes: app.UseEndpoints(endpoints => endpoints.MapGet(...)) (pre-.NET 6 Startup style) |
|
|
54
|
+
| Microsoft.AspNetCore.SignalR | partly | no: app.MapHub<THub>("/hubs/x") route<br>yes: public methods of a Hub subclass, called by clients with InvokeAsync("Name") |
|
|
55
|
+
| System.Net.HttpListener | not yet | no: HttpListener.Prefixes.Add(url) + GetContextAsync loop + path switch |
|
|
56
|
+
|
|
57
|
+
## HTTP client libraries (the calls your code makes to other services)
|
|
58
|
+
|
|
59
|
+
3 supported, 0 partly, 6 not yet.
|
|
60
|
+
|
|
61
|
+
| Name | Status | Ways of using it that were tested |
|
|
62
|
+
|---|---|---|
|
|
63
|
+
| Dapr.Client | not yet | no: DaprClient.InvokeMethodAsync(HttpMethod.Get, "app-id", "path") and CreateInvokeHttpClient("app-id") |
|
|
64
|
+
| docker-compose (deployment) | not yet | no: a compose service name used as the host (http://<service>:8080) for a C# service |
|
|
65
|
+
| Flurl.Http | not yet | no: "url".AppendPathSegments(...).GetJsonAsync<T>() and "url".PostJsonAsync()<br>no: new FlurlClient(base).Request(path).GetJsonAsync<T>() |
|
|
66
|
+
| GraphQL.Client | supported | yes: new GraphQLHttpClient(url, serializer).SendQueryAsync(...) |
|
|
67
|
+
| Microsoft.AspNetCore.SignalR.Client | supported | yes: new HubConnectionBuilder().WithUrl(hubUrl).Build(); InvokeAsync("Method"); On<T>("Event") |
|
|
68
|
+
| Refit | not yet | no: interface with [Get("/x/{id}")] methods + AddRefitClient<T>().ConfigureHttpClient(BaseAddress)<br>no: RestService.For<T>(baseUrl).Method() |
|
|
69
|
+
| RestSharp | supported | yes: new RestRequest(template, Method.Get) + client.ExecuteAsync(request)<br>yes: client.GetJsonAsync<T>(path), PostJsonAsync, ExecutePostAsync |
|
|
70
|
+
| ServiceStack.Client | not yet | no: JsonServiceClient.Get(new Dto{...}) (route from the DTO) and Get<T>("/relative") |
|
|
71
|
+
| System.ServiceModel.Http | not yet | no: new ChannelFactory<T>(binding, new EndpointAddress(url)).CreateChannel().Op() |
|
|
72
|
+
|
|
73
|
+
## The language's own HTTP client
|
|
74
|
+
|
|
75
|
+
2 supported, 2 partly, 2 not yet.
|
|
76
|
+
|
|
77
|
+
| Name | Status | Ways of using it that were tested |
|
|
78
|
+
|---|---|---|
|
|
79
|
+
| Microsoft.Extensions.Http (IHttpClientFactory) | partly | partly: AddHttpClient("name", c => c.BaseAddress = ...) + factory.CreateClient("name").GetAsync(path)<br>yes: AddHttpClient<TClient>(c => c.BaseAddress = ...) and HttpClient injected into TClient |
|
|
80
|
+
| Microsoft.Extensions.Http.Resilience / Polly | supported | yes: AddHttpClient<T>(...).AddStandardResilienceHandler() wrapping a typed client |
|
|
81
|
+
| System.Net.Http.HttpClient | partly | partly: GetAsync/PostAsync/GetStreamAsync with an absolute literal URL<br>partly: SendAsync(new HttpRequestMessage(HttpMethod.Put, url))<br>yes: static HttpClient { BaseAddress = new Uri(...) } + relative path<br>yes: interpolated $"http://host:port/path/{x}" URL<br>yes: "http://host/path/" + id concatenation<br>partly: base URL from IConfiguration["Services:X"] + path<br>partly: new Uri(new Uri(base), relative) as the request URI |
|
|
82
|
+
| System.Net.Http.Json | supported | yes: GetFromJsonAsync / PostAsJsonAsync / PutAsJsonAsync / DeleteFromJsonAsync extensions |
|
|
83
|
+
| System.Net.WebClient | not yet | no: new WebClient().DownloadString(url) / UploadString(url, "POST", body) |
|
|
84
|
+
| System.Net.WebRequest / HttpWebRequest | not yet | no: WebRequest.Create(url).GetResponse(); HttpWebRequest with Method = "POST" |
|
|
85
|
+
|
|
86
|
+
## gRPC
|
|
87
|
+
|
|
88
|
+
5 supported, 2 partly, 1 not yet.
|
|
89
|
+
|
|
90
|
+
| Name | Status | Ways of using it that were tested |
|
|
91
|
+
|---|---|---|
|
|
92
|
+
| Grpc.AspNetCore | partly | yes: class X : {S}.{S}Base with public override Task<R> M(Req, ServerCallContext) (unary)<br>no: app.MapGrpcService<X>() registration (confirming signal)<br>yes: override Task M(Req, IServerStreamWriter<T>, ServerCallContext)<br>yes: override Task<R> M(IAsyncStreamReader<T>, ServerCallContext)<br>yes: override Task M(IAsyncStreamReader<A>, IServerStreamWriter<B>, ServerCallContext)<br>no: AddGrpc(o => o.Interceptors.Add<T>()) (must not hide the service) |
|
|
93
|
+
| Grpc.Core | supported | yes: new Server { Services = { X.BindService(new Impl()) }, Ports = {...} } with Impl : X.XBase<br>yes: new Channel("host:port", ChannelCredentials.Insecure) + new X.XClient(channel) |
|
|
94
|
+
| Grpc.Core.Api | supported | yes: new Method<Req,Res>(MethodType.Unary, "pkg.Svc", "M", m, m) + CallInvoker.BlockingUnaryCall |
|
|
95
|
+
| Grpc.Net.Client | supported | yes: GrpcChannel.ForAddress(url); new {S}.{S}Client(channel); await client.MAsync(req)<br>yes: client.M(req) blocking call, channel address from IConfiguration<br>yes: server/client/bidi streaming calls (no Async twin), ResponseStream.ReadAllAsync, RequestStream.WriteAsync<br>yes: channel.Intercept(interceptor) then new {S}.{S}Client(invoker) |
|
|
96
|
+
| Grpc.Net.ClientFactory | supported | yes: services.AddGrpcClient<{S}.{S}Client>(o => o.Address = new Uri(...)) then the client injected by type |
|
|
97
|
+
| Microsoft.AspNetCore.Grpc.JsonTranscoding | partly | partly: option (google.api.http) = { get: "/v1/orders/{order_id}" } in the proto + AddJsonTranscoding() |
|
|
98
|
+
| protobuf-net.Grpc | not yet | no: channel.CreateGrpcService<IContract>().MAsync(req) |
|
|
99
|
+
| protobuf-net.Grpc.AspNetCore | supported | yes: [Service("pkg.Svc")] / [ServiceContract(Name)] interface + [Operation] methods, MapGrpcService<Impl>(), AddCodeFirstGrpc() |
|
|
100
|
+
|
|
101
|
+
## Databases and data stores
|
|
102
|
+
|
|
103
|
+
10 supported, 5 partly, 11 not yet.
|
|
104
|
+
|
|
105
|
+
| Name | Status | Ways of using it that were tested |
|
|
106
|
+
|---|---|---|
|
|
107
|
+
| AWSSDK.DynamoDBv2 | partly | yes: PutItemAsync/QueryAsync(new XRequest { TableName = "t" })<br>no: DynamoDBContext.SaveAsync(obj) with [DynamoDBTable("t")] |
|
|
108
|
+
| AWSSDK.S3 | supported | yes: PutObjectAsync(new PutObjectRequest { BucketName = "b" }) |
|
|
109
|
+
| Azure.Storage.Blobs | supported | yes: GetBlobContainerClient("name").UploadBlobAsync |
|
|
110
|
+
| CassandraCSharpDriver | supported | yes: ISession.Execute(cql) / ExecuteAsync(new SimpleStatement(cql)) |
|
|
111
|
+
| Dapper | not yet | no: conn.QueryFirstOrDefaultAsync<T>(sql) / Query<T>(const sql) / QueryMultiple<br>no: conn.ExecuteAsync("INSERT ...") |
|
|
112
|
+
| Dapper.Contrib | not yet | no: conn.Get<T>(id) / Insert<T> with [Table("name")] |
|
|
113
|
+
| Dapr.Client | not yet | no: DaprClient.SaveStateAsync("store", key, value) |
|
|
114
|
+
| Elastic.Clients.Elasticsearch | not yet | no: ElasticsearchClient.IndexAsync(doc, "index") / SearchAsync<T>(s => s.Index("x")) |
|
|
115
|
+
| EntityFramework (EF6) | not yet | no: System.Data.Entity DbContext + DbSet + ToTable + Database.ExecuteSqlCommand |
|
|
116
|
+
| linq2db | not yet | no: [Table("t")] + GetTable<T>() |
|
|
117
|
+
| Marten | not yet | no: IDocumentSession.Store(doc) / Query<T>() over PostgreSQL |
|
|
118
|
+
| Microsoft.Azure.Cosmos | partly | partly: client.GetContainer(db, "name") in a field + UpsertItemAsync / GetItemQueryIterator |
|
|
119
|
+
| Microsoft.Data.SqlClient | partly | yes: new SqlCommand("SELECT ... FROM t", conn) + ExecuteReaderAsync/ExecuteScalar<br>no: conn.CreateCommand(); cmd.CommandText = "UPDATE ..."; ExecuteNonQuery()<br>no: CommandType.StoredProcedure with the procedure name as command text<br>no: SqlBulkCopy { DestinationTableName = "t" }.WriteToServerAsync |
|
|
120
|
+
| Microsoft.Data.Sqlite | not yet | no: conn.CreateCommand() + CommandText |
|
|
121
|
+
| Microsoft.EntityFrameworkCore | partly | yes: DbSet<T> property + LINQ (Where/FirstOrDefaultAsync/ToListAsync)<br>yes: [Table("name")] on the entity<br>no: modelBuilder.Entity<T>().ToTable("name")<br>no: context.Set<T>() instead of a DbSet property<br>partly: FromSqlRaw / ExecuteSqlRawAsync with SQL text<br>yes: ExecuteUpdateAsync / ExecuteDeleteAsync bulk operations (EF Core 7+) |
|
|
122
|
+
| Microsoft.Extensions.Caching.Distributed | supported | yes: IDistributedCache.SetAsync/GetAsync (Redis backed) |
|
|
123
|
+
| MongoDB.Driver | partly | partly: GetCollection<T>("name") stored in a field, then Find/InsertOneAsync/UpdateOneAsync on the field<br>partly: db.GetCollection<T>("name").CountDocumentsAsync(...) inline |
|
|
124
|
+
| MySql.Data | supported | yes: Oracle MySql.Data MySqlCommand (namespace MySql.Data.MySqlClient) |
|
|
125
|
+
| MySqlConnector | supported | yes: MySqlCommand(sql, conn) + ExecuteScalarAsync |
|
|
126
|
+
| NEST | not yet | no: ElasticClient with DefaultIndex, IndexDocument, Search(s => s.Index("x")) |
|
|
127
|
+
| NHibernate | not yet | no: session.Query<T>(), Save, CreateSQLQuery; FluentNHibernate ClassMap Table("t") |
|
|
128
|
+
| Npgsql | supported | yes: NpgsqlCommand(sql, conn) + ExecuteScalarAsync<br>yes: NpgsqlDataSource.Create(cs).CreateCommand(sql) (Npgsql 7+)<br>yes: BeginBinaryImportAsync("COPY t ... FROM STDIN") |
|
|
129
|
+
| Oracle.ManagedDataAccess | supported | yes: OracleCommand(sql, conn) |
|
|
130
|
+
| StackExchange.Redis | supported | yes: IDatabase.StringSetAsync/StringGetAsync/HashIncrementAsync/ListLeftPushAsync |
|
|
131
|
+
| System.Data.Common (ADO.NET) | not yet | no: DbProviderFactories.GetFactory + DbConnection.CreateCommand + DbCommand |
|
|
132
|
+
| System.Data.SqlClient | supported | yes: the older package, same SqlCommand API |
|
|
133
|
+
|
|
134
|
+
## Messaging and events (queues, topics, streams)
|
|
135
|
+
|
|
136
|
+
10 supported, 8 partly, 12 not yet.
|
|
137
|
+
|
|
138
|
+
| Name | Status | Ways of using it that were tested |
|
|
139
|
+
|---|---|---|
|
|
140
|
+
| .NET events and delegates | not yet | no: event EventHandler<T> OnX; OnX?.Invoke(...) inside one process |
|
|
141
|
+
| AWSSDK.EventBridge | partly | partly: PutEventsAsync(new PutEventsRequest { Entries = { new() { EventBusName, DetailType } } }) |
|
|
142
|
+
| AWSSDK.SimpleNotificationService | supported | yes: PublishAsync(new PublishRequest { TopicArn }) and PublishAsync(topicArn, msg) |
|
|
143
|
+
| AWSSDK.SQS | supported | yes: SendMessageAsync(queueUrl, body) with the URL in a const<br>yes: ReceiveMessageAsync(new ReceiveMessageRequest { QueueUrl = ... }) |
|
|
144
|
+
| Azure.Messaging.EventGrid | not yet | no: EventGridPublisherClient(endpoint, cred).SendEventAsync(new EventGridEvent(subject, type, ...)) |
|
|
145
|
+
| Azure.Messaging.EventHubs | not yet | no: new EventHubProducerClient(cs, "hub").SendAsync(events) |
|
|
146
|
+
| Azure.Messaging.EventHubs.Processor | not yet | no: new EventProcessorClient(store, group, cs, "hub") + ProcessEventAsync += handler |
|
|
147
|
+
| Azure.Messaging.ServiceBus | partly | yes: client.CreateSender("queue").SendMessageAsync / ScheduleMessageAsync<br>no: CreateProcessor(topic, sub) + ProcessMessageAsync += handler + StartProcessingAsync<br>yes: CreateReceiver("queue").ReceiveMessageAsync() |
|
|
148
|
+
| Azure.Storage.Queues | not yet | no: new QueueClient(cs, "name").SendMessageAsync / ReceiveMessagesAsync |
|
|
149
|
+
| Confluent.Kafka | supported | yes: producer.ProduceAsync(topic, msg) and Produce(topic, msg, handler), topic as literal or const<br>yes: consumer.Subscribe(topic) + Consume loop in a BackgroundService<br>yes: consumer.Subscribe(new[] { "a", "b" }) |
|
|
150
|
+
| Dapr.Client / Dapr.AspNetCore | partly | partly: DaprClient.PublishEventAsync(pubsub, topic, data); [Topic(pubsub, topic)] or .WithTopic |
|
|
151
|
+
| DotNetCore.CAP | supported | yes: ICapPublisher.PublishAsync(name, data) and [CapSubscribe(name)] |
|
|
152
|
+
| EasyNetQ | not yet | no: bus.PubSub.PublishAsync / SubscribeAsync<T>(id, handler); SendReceive.SendAsync/ReceiveAsync(queue) |
|
|
153
|
+
| Google.Cloud.PubSub.V1 | supported | yes: PublisherClient.CreateAsync(TopicName).PublishAsync; SubscriberClient.CreateAsync(SubscriptionName).StartAsync |
|
|
154
|
+
| Hangfire.Core | not yet | no: BackgroundJob.Enqueue/Schedule, RecurringJob.AddOrUpdate |
|
|
155
|
+
| MassTransit | partly | yes: IPublishEndpoint.Publish(new T()) and IConsumer<T>.Consume<br>yes: GetSendEndpoint(new Uri("queue:name")).Send(msg) + ReceiveEndpoint("name")<br>partly: IRequestClient<T>.GetResponse<TRes>(msg) and RespondAsync |
|
|
156
|
+
| MediatR | supported | yes: IMediator.Send/Publish and IRequestHandler/INotificationHandler (in-process) |
|
|
157
|
+
| Microsoft.AspNetCore.SignalR | not yet | no: Clients.All/Caller/Group(x).SendAsync("Event", ...) and IHubContext<T> |
|
|
158
|
+
| Microsoft.Azure.Functions.Worker | not yet | no: [ServiceBusOutput("q")] on the function (return value is the message) |
|
|
159
|
+
| Microsoft.Azure.Functions.Worker / WebJobs | not yet | no: [ServiceBusTrigger("q")], [QueueTrigger], [KafkaTrigger], [EventHubTrigger], [TimerTrigger] on a PARAMETER |
|
|
160
|
+
| MQTTnet | supported | yes: client.PublishAsync(builder.WithTopic(t)) and SubscribeAsync(filter) + ApplicationMessageReceivedAsync += |
|
|
161
|
+
| NATS.Client | supported | yes: conn.Publish(subject, bytes) and conn.SubscribeAsync(subject, handler) |
|
|
162
|
+
| NATS.Net | partly | partly: NatsConnection.PublishAsync(subject, data); await foreach SubscribeAsync<T>(subject) |
|
|
163
|
+
| NServiceBus | partly | yes: IHandleMessages<T>.Handle + context.Publish<br>partly: IMessageSession.Send(msg) with RouteToEndpoint |
|
|
164
|
+
| Quartz | partly | partly: IScheduler.ScheduleJob(job, trigger) and IJob.Execute |
|
|
165
|
+
| RabbitMQ.Client | partly | yes: channel.BasicPublish("exchange", "routing.key", props, body)<br>yes: BasicPublish(exchange: "", routingKey: "q", ...) with named arguments<br>partly: EventingBasicConsumer + Received += handler + BasicConsume(queue: "q", ...)<br>yes: v7 BasicConsumeAsync + AsyncEventingBasicConsumer.ReceivedAsync<br>no: class X : DefaultBasicConsumer overriding HandleBasicDeliver |
|
|
166
|
+
| Rebus | supported | yes: IBus.Send(msg) and IHandleMessages<T> |
|
|
167
|
+
| StackExchange.Redis | supported | yes: ISubscriber.Publish/PublishAsync(RedisChannel.Literal("x"), msg) and Subscribe(channel, handler) |
|
|
168
|
+
| System.Threading.Channels | not yet | no: Channel.CreateBounded/Unbounded<T>(), Writer.WriteAsync, Reader.ReadAllAsync (in-process) |
|
|
169
|
+
| WolverineFx | not yet | no: IMessageBus.PublishAsync/SendAsync and convention handlers (class *Handler, method Handle) |
|
|
170
|
+
|
|
171
|
+
## Build tools and package managers
|
|
172
|
+
|
|
173
|
+
9 supported, 2 partly, 0 not yet.
|
|
174
|
+
|
|
175
|
+
| Name | Status | Ways of using it that were tested |
|
|
176
|
+
|---|---|---|
|
|
177
|
+
| Microsoft.Build.Traversal (dirs.proj) | supported | yes: dirs.proj at the root building src/**/*.csproj, no .sln |
|
|
178
|
+
| MSBuild + .fsproj (F#) | partly | partly: a C# Web API calling an F# library in the same solution |
|
|
179
|
+
| MSBuild + .sln (SDK-style csproj) | supported | yes: .sln, src/ and tests/: Web SDK API and Worker SDK service with no <OutputType>, a class library, an xUnit project |
|
|
180
|
+
| MSBuild + .slnx and .slnf | supported | yes: XML solution file (.slnx) and a solution filter, no .sln |
|
|
181
|
+
| MSBuild + .vbproj (VB.NET) | partly | partly: a C# console app calling a VB.NET library |
|
|
182
|
+
| MSBuild Directory.Build.props / .targets | supported | yes: OutputType=Exe inherited from apps/Directory.Build.props; the csproj files are one line |
|
|
183
|
+
| MSBuild legacy (non-SDK) csproj, .NET Framework | supported | yes: ToolsVersion csproj with <Compile Include>, packages.config, restored packages/ folder; ASP.NET MVC 5 app with OutputType Library + Web.config + Global.asax |
|
|
184
|
+
| MSBuild shared project (.shproj + .projitems) | supported | yes: files compiled into each importing app; the shared folder has no assembly |
|
|
185
|
+
| NuGet central package management | supported | yes: Directory.Packages.props with PackageVersion; PackageReference without Version; global.json; nuget.config |
|
|
186
|
+
| NUKE, Cake, dotnet tool, Roslyn source generator | supported | yes: build/_build.csproj (NUKE, Exe), build.cake, tools/Orders.Cli (PackAsTool), src/Orders.Generators (IsRoslynComponent, referenced as Analyzer), one Web API |
|
|
187
|
+
| project.json (.NET Core 1.0 preview tooling) | supported | yes: project.json per project, global.json "projects", no csproj |
|
|
188
|
+
|
|
189
|
+
## Project and folder layouts
|
|
190
|
+
|
|
191
|
+
7 supported, 0 partly, 0 not yet.
|
|
192
|
+
|
|
193
|
+
| Name | Status | Ways of using it that were tested |
|
|
194
|
+
|---|---|---|
|
|
195
|
+
| Azure Functions project | supported | yes: isolated worker app (OutputType Exe, AzureFunctionsVersion, host.json) and in-process app (Microsoft.NET.Sdk.Functions, no OutputType) |
|
|
196
|
+
| Blazor WebAssembly hosted template | supported | yes: Client (BlazorWebAssembly SDK), Server (Web SDK, references Client), Shared |
|
|
197
|
+
| C# top-level statements (Program.cs) | supported | yes: Program.cs with no class or Main, the default template since .NET 6 |
|
|
198
|
+
| MSBuild output folders | supported | yes: bin/, obj/ (generated *.g.cs), .vs/, TestResults/, artifacts/, packages/ present, no .gitignore<br>yes: the same with the standard Visual Studio .gitignore ([Bb]in/, [Oo]bj/, **/[Pp]ackages/*) |
|
|
199
|
+
| MSBuild SDK-style | supported | yes: a console app (OutputType Exe, top-level statements), a Worker SDK service with no OutputType, a library; projects at the repo root, no solution<br>yes: one csproj at the repository root, folders for controllers, services and models<br>yes: services/<name>/<name>.csproj and libs/<name>, no solution, no deploy descriptor |
|
|
200
|
+
| MSBuild SDK-style, WPF | supported | yes: WPF app (OutputType WinExe, UseWPF, net8.0-windows) with XAML code-behind, and a library |
|
|
201
|
+
| MSBuild test projects (xUnit v2, xUnit v3, NUnit, MSTest) | supported | yes: unit and integration tests; the xUnit v3 project is OutputType Exe; one MSTest project not named *.Tests |
|
|
202
|
+
|
|
203
|
+
## Deployment files
|
|
204
|
+
|
|
205
|
+
3 supported, 0 partly, 0 not yet.
|
|
206
|
+
|
|
207
|
+
| Name | Status | Ways of using it that were tested |
|
|
208
|
+
|---|---|---|
|
|
209
|
+
| .NET Aspire AppHost | supported | yes: AppHost (Aspire.AppHost.Sdk, IsAspireHost) declaring AddProject<Projects.X>("name"), ServiceDefaults library, two services, service discovery URL http://catalog-api |
|
|
210
|
+
| ASP.NET Core address settings | supported | yes: launchSettings.json applicationUrl, appsettings.json Kestrel:Endpoints:Http:Url, compose ASPNETCORE_URLS |
|
|
211
|
+
| Dockerfile + docker-compose (Visual Studio container tools) | supported | yes: Dockerfile inside each project folder, built with context "."; compose services with context: . and dockerfile: src/X/Dockerfile |
|