Skip to content

Commit fc6f1e3

Browse files
chore(internal): codegen related update
1 parent 1dbb15f commit fc6f1e3

File tree

3 files changed

+149
-0
lines changed

3 files changed

+149
-0
lines changed

README.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ The Terminal Java SDK is similar to the Terminal Kotlin SDK but with minor diffe
1313

1414
It is generated with [Stainless](https://www.stainless.com/).
1515

16+
## MCP Server
17+
18+
Use the Terminal MCP Server to enable AI assistants to interact with this API, allowing them to explore endpoints, make test requests, and use documentation to help integrate this SDK into your application.
19+
20+
[![Add to Cursor](https://cursor.com/deeplink/mcp-install-dark.svg)](https://cursor.com/en-US/install-mcp?name=%40terminaldotshop%2Fmcp&config=eyJjb21tYW5kIjoibnB4IiwiYXJncyI6WyIteSIsIkB0ZXJtaW5hbGRvdHNob3AvbWNwIl19)
21+
[![Install in VS Code](https://img.shields.io/badge/_-Add_to_VS_Code-blue?style=for-the-badge&logo=data:image/svg%2bxml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIGZpbGw9Im5vbmUiIHZpZXdCb3g9IjAgMCA0MCA0MCI+PHBhdGggZmlsbD0iI0VFRSIgZmlsbC1ydWxlPSJldmVub2RkIiBkPSJNMzAuMjM1IDM5Ljg4NGEyLjQ5MSAyLjQ5MSAwIDAgMS0xLjc4MS0uNzNMMTIuNyAyNC43OGwtMy40NiAyLjYyNC0zLjQwNiAyLjU4MmExLjY2NSAxLjY2NSAwIDAgMS0xLjA4Mi4zMzggMS42NjQgMS42NjQgMCAwIDEtMS4wNDYtLjQzMWwtMi4yLTJhMS42NjYgMS42NjYgMCAwIDEgMC0yLjQ2M0w3LjQ1OCAyMCA0LjY3IDE3LjQ1MyAxLjUwNyAxNC41N2ExLjY2NSAxLjY2NSAwIDAgMSAwLTIuNDYzbDIuMi0yYTEuNjY1IDEuNjY1IDAgMCAxIDIuMTMtLjA5N2w2Ljg2MyA1LjIwOUwyOC40NTIuODQ0YTIuNDg4IDIuNDg4IDAgMCAxIDEuODQxLS43MjljLjM1MS4wMDkuNjk5LjA5MSAxLjAxOS4yNDVsOC4yMzYgMy45NjFhMi41IDIuNSAwIDAgMSAxLjQxNSAyLjI1M3YuMDk5LS4wNDVWMzMuMzd2LS4wNDUuMDk1YTIuNTAxIDIuNTAxIDAgMCAxLTEuNDE2IDIuMjU3bC04LjIzNSAzLjk2MWEyLjQ5MiAyLjQ5MiAwIDAgMS0xLjA3Ny4yNDZabS43MTYtMjguOTQ3LTExLjk0OCA5LjA2MiAxMS45NTIgOS4wNjUtLjAwNC0xOC4xMjdaIi8+PC9zdmc+)](https://vscode.stainless.com/mcp/%7B%22name%22%3A%22%40terminaldotshop%2Fmcp%22%2C%22command%22%3A%22npx%22%2C%22args%22%3A%5B%22-y%22%2C%22%40terminaldotshop%2Fmcp%22%5D%7D)
22+
23+
> Note: You may need to set environment variables in your MCP client.
24+
1625
<!-- x-release-please-start-version -->
1726

1827
The REST API documentation can be found on [terminal.shop](https://terminal.shop/docs). Javadocs are available on [javadoc.io](https://javadoc.io/doc/shop.terminal.api/terminal-java/2.5.0).

terminal-java-core/src/main/kotlin/shop/terminal/api/core/http/HttpRequest.kt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package shop.terminal.api.core.http
22

3+
import java.net.URLEncoder
34
import shop.terminal.api.core.checkRequired
45
import shop.terminal.api.core.toImmutable
56

@@ -13,6 +14,35 @@ private constructor(
1314
@get:JvmName("body") val body: HttpRequestBody?,
1415
) {
1516

17+
fun url(): String = buildString {
18+
append(baseUrl)
19+
20+
pathSegments.forEach { segment ->
21+
if (!endsWith("/")) {
22+
append("/")
23+
}
24+
append(URLEncoder.encode(segment, "UTF-8"))
25+
}
26+
27+
if (queryParams.isEmpty()) {
28+
return@buildString
29+
}
30+
31+
append("?")
32+
var isFirst = true
33+
queryParams.keys().forEach { key ->
34+
queryParams.values(key).forEach { value ->
35+
if (!isFirst) {
36+
append("&")
37+
}
38+
append(URLEncoder.encode(key, "UTF-8"))
39+
append("=")
40+
append(URLEncoder.encode(value, "UTF-8"))
41+
isFirst = false
42+
}
43+
}
44+
}
45+
1646
fun toBuilder(): Builder = Builder().from(this)
1747

1848
override fun toString(): String =
Lines changed: 110 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
package shop.terminal.api.core.http
2+
3+
import org.assertj.core.api.Assertions.assertThat
4+
import org.junit.jupiter.params.ParameterizedTest
5+
import org.junit.jupiter.params.provider.EnumSource
6+
7+
internal class HttpRequestTest {
8+
9+
enum class UrlTestCase(val request: HttpRequest, val expectedUrl: String) {
10+
BASE_URL_ONLY(
11+
HttpRequest.builder().method(HttpMethod.GET).baseUrl("https://api.example.com").build(),
12+
expectedUrl = "https://api.example.com",
13+
),
14+
BASE_URL_WITH_TRAILING_SLASH(
15+
HttpRequest.builder()
16+
.method(HttpMethod.GET)
17+
.baseUrl("https://api.example.com/")
18+
.build(),
19+
expectedUrl = "https://api.example.com/",
20+
),
21+
SINGLE_PATH_SEGMENT(
22+
HttpRequest.builder()
23+
.method(HttpMethod.GET)
24+
.baseUrl("https://api.example.com")
25+
.addPathSegment("users")
26+
.build(),
27+
expectedUrl = "https://api.example.com/users",
28+
),
29+
MULTIPLE_PATH_SEGMENTS(
30+
HttpRequest.builder()
31+
.method(HttpMethod.GET)
32+
.baseUrl("https://api.example.com")
33+
.addPathSegments("users", "123", "profile")
34+
.build(),
35+
expectedUrl = "https://api.example.com/users/123/profile",
36+
),
37+
PATH_SEGMENT_WITH_SPECIAL_CHARS(
38+
HttpRequest.builder()
39+
.method(HttpMethod.GET)
40+
.baseUrl("https://api.example.com")
41+
.addPathSegment("user name")
42+
.build(),
43+
expectedUrl = "https://api.example.com/user+name",
44+
),
45+
SINGLE_QUERY_PARAM(
46+
HttpRequest.builder()
47+
.method(HttpMethod.GET)
48+
.baseUrl("https://api.example.com")
49+
.addPathSegment("users")
50+
.putQueryParam("limit", "10")
51+
.build(),
52+
expectedUrl = "https://api.example.com/users?limit=10",
53+
),
54+
MULTIPLE_QUERY_PARAMS(
55+
HttpRequest.builder()
56+
.method(HttpMethod.GET)
57+
.baseUrl("https://api.example.com")
58+
.addPathSegment("users")
59+
.putQueryParam("limit", "10")
60+
.putQueryParam("offset", "20")
61+
.build(),
62+
expectedUrl = "https://api.example.com/users?limit=10&offset=20",
63+
),
64+
QUERY_PARAM_WITH_SPECIAL_CHARS(
65+
HttpRequest.builder()
66+
.method(HttpMethod.GET)
67+
.baseUrl("https://api.example.com")
68+
.addPathSegment("search")
69+
.putQueryParam("q", "hello world")
70+
.build(),
71+
expectedUrl = "https://api.example.com/search?q=hello+world",
72+
),
73+
MULTIPLE_VALUES_SAME_PARAM(
74+
HttpRequest.builder()
75+
.method(HttpMethod.GET)
76+
.baseUrl("https://api.example.com")
77+
.addPathSegment("users")
78+
.putQueryParams("tags", listOf("admin", "user"))
79+
.build(),
80+
expectedUrl = "https://api.example.com/users?tags=admin&tags=user",
81+
),
82+
BASE_URL_WITH_TRAILING_SLASH_AND_PATH(
83+
HttpRequest.builder()
84+
.method(HttpMethod.GET)
85+
.baseUrl("https://api.example.com/")
86+
.addPathSegment("users")
87+
.build(),
88+
expectedUrl = "https://api.example.com/users",
89+
),
90+
COMPLEX_URL(
91+
HttpRequest.builder()
92+
.method(HttpMethod.POST)
93+
.baseUrl("https://api.example.com")
94+
.addPathSegments("v1", "users", "123")
95+
.putQueryParams("include", listOf("profile", "settings"))
96+
.putQueryParam("format", "json")
97+
.build(),
98+
expectedUrl =
99+
"https://api.example.com/v1/users/123?include=profile&include=settings&format=json",
100+
),
101+
}
102+
103+
@ParameterizedTest
104+
@EnumSource
105+
fun url(testCase: UrlTestCase) {
106+
val actualUrl = testCase.request.url()
107+
108+
assertThat(actualUrl).isEqualTo(testCase.expectedUrl)
109+
}
110+
}

0 commit comments

Comments
 (0)