@arrirpc/codegen-kotlin 0.60.3 → 0.61.0
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +72 -1
- package/dist/index.cjs +131 -133
- package/dist/index.d.cts +3 -3
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.mjs +131 -133
- package/package.json +2 -2
package/README.md
CHANGED
@@ -24,7 +24,7 @@ export default defineConfig({
|
|
24
24
|
| --------------------- | ------------------------------------------------------------- |
|
25
25
|
| clientName | The name of the generated client class (Defaults to "Client") |
|
26
26
|
| outputFile (required) | Path to the file that will be created by the generator |
|
27
|
-
|
|
27
|
+
| typePrefix | Add a prefix to the generated class names |
|
28
28
|
|
29
29
|
### 2) Install dependencies
|
30
30
|
|
@@ -72,6 +72,77 @@ val service = MyClientUsersService(
|
|
72
72
|
)
|
73
73
|
```
|
74
74
|
|
75
|
+
### Calling Procedures
|
76
|
+
|
77
|
+
#### Standard HTTP Procedures
|
78
|
+
|
79
|
+
```kotlin
|
80
|
+
runBlocking {
|
81
|
+
// procedure with no parameters
|
82
|
+
val getUsersResponse = myClient.users.getUsers()
|
83
|
+
|
84
|
+
// procedure with parameters
|
85
|
+
val getUserResponse = myClient.users.getUser(GetUserParams(userId = "12345"))
|
86
|
+
}
|
87
|
+
```
|
88
|
+
|
89
|
+
#### Event Stream Procedures
|
90
|
+
|
91
|
+
##### Basic Usage
|
92
|
+
|
93
|
+
```kotlin
|
94
|
+
runBlocking {
|
95
|
+
myClient.users.watchUserChanges(
|
96
|
+
onData { message ->
|
97
|
+
println("New message: ${message}")
|
98
|
+
},
|
99
|
+
onOpen {
|
100
|
+
println("Connection established")
|
101
|
+
}
|
102
|
+
onRequestError { err ->
|
103
|
+
println("Error connecting to server: ${err}")
|
104
|
+
},
|
105
|
+
onResponseError { err ->
|
106
|
+
println("Server returned an error: ${err.code} ${err.message}")
|
107
|
+
},
|
108
|
+
onClose {
|
109
|
+
println("Connection closed")
|
110
|
+
}
|
111
|
+
)
|
112
|
+
}
|
113
|
+
```
|
114
|
+
|
115
|
+
##### Cancelling Requests
|
116
|
+
|
117
|
+
Event stream procedures can be cancelled from inside one of the hooks by throwing a `CancellationException`
|
118
|
+
|
119
|
+
```kotlin
|
120
|
+
runBlocking {
|
121
|
+
myClient.users.watchUserChanges(
|
122
|
+
onResponseError { err ->
|
123
|
+
println("Server returned an error: ${err.code} ${err.message}")
|
124
|
+
throw CancellationException()
|
125
|
+
}
|
126
|
+
)
|
127
|
+
}
|
128
|
+
```
|
129
|
+
|
130
|
+
You can also spawn a job and cancel that job in order to cancel the Event stream procedure from the outside
|
131
|
+
|
132
|
+
```kotlin
|
133
|
+
val job = someCoroutineScope.launch {
|
134
|
+
myClient.users.watchUserChanges()
|
135
|
+
}
|
136
|
+
job.cancel()
|
137
|
+
```
|
138
|
+
|
139
|
+
##### Other Options
|
140
|
+
|
141
|
+
| Option | Type | Description |
|
142
|
+
| -------------- | ----- | ------------------------------------------------------------------------------------------------------- |
|
143
|
+
| bufferCapacity | Int | Max buffer size that can be allocated towards reading messages received. Default is 1024 \* 1024 (1MB). |
|
144
|
+
| maxBackoffTime | Long? | Max wait time between retries in milliseconds. Default is 30000ms |
|
145
|
+
|
75
146
|
### Using Arri Models
|
76
147
|
|
77
148
|
All generated models will be data classes. They will have access to the following features:
|
package/dist/index.cjs
CHANGED
@@ -65,7 +65,7 @@ function getClassName(schema, context) {
|
|
65
65
|
normalize: true
|
66
66
|
})
|
67
67
|
);
|
68
|
-
return `${context.
|
68
|
+
return `${context.typePrefix}${className2}`;
|
69
69
|
}
|
70
70
|
const depth = instanceDepth(context);
|
71
71
|
if (depth === 1 && !context.discriminatorKey) {
|
@@ -74,7 +74,7 @@ function getClassName(schema, context) {
|
|
74
74
|
normalize: true
|
75
75
|
})
|
76
76
|
);
|
77
|
-
return `${context.
|
77
|
+
return `${context.typePrefix}${className2}`;
|
78
78
|
}
|
79
79
|
if (context.discriminatorParentId && context.discriminatorKey && context.discriminatorValue) {
|
80
80
|
const className2 = kotlinClassName(
|
@@ -83,7 +83,7 @@ function getClassName(schema, context) {
|
|
83
83
|
{ normalize: true }
|
84
84
|
)
|
85
85
|
);
|
86
|
-
return `${context.
|
86
|
+
return `${context.typePrefix}${className2}`;
|
87
87
|
}
|
88
88
|
const className = kotlinClassName(
|
89
89
|
codegenUtils.pascalCase(
|
@@ -93,7 +93,7 @@ function getClassName(schema, context) {
|
|
93
93
|
}
|
94
94
|
)
|
95
95
|
);
|
96
|
-
return `${context.
|
96
|
+
return `${context.typePrefix}${className}`;
|
97
97
|
}
|
98
98
|
function instanceDepth(context) {
|
99
99
|
const parts = context.instancePath.split("/");
|
@@ -172,7 +172,7 @@ function kotlinArrayFromSchema(schema, context) {
|
|
172
172
|
const nullable = isNullable(schema, context);
|
173
173
|
const defaultValue = nullable ? "null" : "mutableListOf()";
|
174
174
|
const subType = kotlinTypeFromSchema(schema.elements, {
|
175
|
-
|
175
|
+
typePrefix: context.typePrefix,
|
176
176
|
clientName: context.clientName,
|
177
177
|
clientVersion: context.clientVersion,
|
178
178
|
instancePath: `${context.instancePath}/[Element]`,
|
@@ -313,7 +313,7 @@ function kotlinObjectFromSchema(schema, context) {
|
|
313
313
|
kotlinKeys.push(kotlinKey);
|
314
314
|
const prop = schema.properties[key];
|
315
315
|
const type = kotlinTypeFromSchema(prop, {
|
316
|
-
|
316
|
+
typePrefix: context.typePrefix,
|
317
317
|
clientName: context.clientName,
|
318
318
|
clientVersion: context.clientVersion,
|
319
319
|
instancePath: `/${className}/${key}`,
|
@@ -347,7 +347,7 @@ function kotlinObjectFromSchema(schema, context) {
|
|
347
347
|
const kotlinKey = kotlinIdentifier(key);
|
348
348
|
kotlinKeys.push(kotlinKey);
|
349
349
|
const type = kotlinTypeFromSchema(schema.optionalProperties[key], {
|
350
|
-
|
350
|
+
typePrefix: context.typePrefix,
|
351
351
|
clientName: context.clientName,
|
352
352
|
clientVersion: context.clientVersion,
|
353
353
|
instancePath: `/${className}/${key}`,
|
@@ -446,7 +446,7 @@ function kotlinDiscriminatorFromSchema(schema, context) {
|
|
446
446
|
for (const key of Object.keys(schema.mapping)) {
|
447
447
|
const subSchema = schema.mapping[key];
|
448
448
|
const subType = kotlinObjectFromSchema(subSchema, {
|
449
|
-
|
449
|
+
typePrefix: context.typePrefix,
|
450
450
|
clientName: context.clientName,
|
451
451
|
clientVersion: context.clientVersion,
|
452
452
|
instancePath: context.instancePath,
|
@@ -634,7 +634,7 @@ function kotlinEnumFromSchema(schema, context) {
|
|
634
634
|
function kotlinMapFromSchema(schema, context) {
|
635
635
|
const nullable = isNullable(schema, context);
|
636
636
|
const subType = kotlinTypeFromSchema(schema.values, {
|
637
|
-
|
637
|
+
typePrefix: context.typePrefix,
|
638
638
|
clientName: context.clientName,
|
639
639
|
clientVersion: context.clientVersion,
|
640
640
|
instancePath: `${context.instancePath}/[value]`,
|
@@ -1129,8 +1129,8 @@ function kotlinProcedureFromSchema(schema, context) {
|
|
1129
1129
|
}
|
1130
1130
|
function kotlinHttpRpcFromSchema(schema, context) {
|
1131
1131
|
const name = getProcedureName(context);
|
1132
|
-
const params = schema.params ? kotlinClassName(`${context.
|
1133
|
-
const response = schema.response ? kotlinClassName(`${context.
|
1132
|
+
const params = schema.params ? kotlinClassName(`${context.typePrefix}_${schema.params}`) : void 0;
|
1133
|
+
const response = schema.response ? kotlinClassName(`${context.typePrefix}_${schema.response}`) : void 0;
|
1134
1134
|
const codeComment = getCodeComment(
|
1135
1135
|
{
|
1136
1136
|
description: schema.description,
|
@@ -1140,40 +1140,36 @@ function kotlinHttpRpcFromSchema(schema, context) {
|
|
1140
1140
|
"method"
|
1141
1141
|
);
|
1142
1142
|
if (schema.isEventStream) {
|
1143
|
-
return `${codeComment}fun ${name}(
|
1144
|
-
scope: CoroutineScope,
|
1143
|
+
return `${codeComment}suspend fun ${name}(
|
1145
1144
|
${params ? `params: ${params},` : ""}
|
1146
1145
|
lastEventId: String? = null,
|
1147
|
-
bufferCapacity: Int = 1024,
|
1146
|
+
bufferCapacity: Int = 1024 * 1024,
|
1148
1147
|
onOpen: ((response: HttpResponse) -> Unit) = {},
|
1149
1148
|
onClose: (() -> Unit) = {},
|
1150
|
-
|
1151
|
-
|
1149
|
+
onRequestError: ((error: Exception) -> Unit) = {},
|
1150
|
+
onResponseError: ((error: ${context.clientName}Error) -> Unit) = {},
|
1152
1151
|
onData: ((${response ? `data: ${response}` : ""}) -> Unit) = {},
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
|
1169
|
-
|
1170
|
-
|
1171
|
-
|
1172
|
-
|
1173
|
-
|
1174
|
-
)
|
1175
|
-
}
|
1176
|
-
return job
|
1152
|
+
maxBackoffTime: Long? = null,
|
1153
|
+
): Unit {
|
1154
|
+
__handleSseRequest(
|
1155
|
+
httpClient = httpClient,
|
1156
|
+
url = "$baseUrl${schema.path}",
|
1157
|
+
method = HttpMethod.${codegenUtils.pascalCase(schema.method, { normalize: true })},
|
1158
|
+
params = ${params ? "params" : "null"},
|
1159
|
+
headers = headers,
|
1160
|
+
backoffTime = 0,
|
1161
|
+
maxBackoffTime = maxBackoffTime ?: 30000L,
|
1162
|
+
lastEventId = lastEventId,
|
1163
|
+
bufferCapacity = bufferCapacity,
|
1164
|
+
onOpen = onOpen,
|
1165
|
+
onClose = onClose,
|
1166
|
+
onRequestError = onRequestError,
|
1167
|
+
onResponseError = onResponseError,
|
1168
|
+
onData = { str ->
|
1169
|
+
${response ? `val data = ${response}.fromJson(str)` : ""}
|
1170
|
+
onData(${response ? "data" : ""})
|
1171
|
+
}
|
1172
|
+
)
|
1177
1173
|
}`;
|
1178
1174
|
}
|
1179
1175
|
const headingCheck = `if (response.headers["Content-Type"] != "application/json") {
|
@@ -1301,7 +1297,7 @@ const kotlinClientGenerator = codegenUtils.defineGeneratorPlugin(
|
|
1301
1297
|
function kotlinClientFromAppDefinition(def, options) {
|
1302
1298
|
const clientName = kotlinClassName(options.clientName ?? "Client");
|
1303
1299
|
const context = {
|
1304
|
-
|
1300
|
+
typePrefix: options.typePrefix ?? "",
|
1305
1301
|
clientName,
|
1306
1302
|
clientVersion: def.info?.version ?? "",
|
1307
1303
|
instancePath: "",
|
@@ -1312,7 +1308,7 @@ function kotlinClientFromAppDefinition(def, options) {
|
|
1312
1308
|
for (const key of Object.keys(def.definitions)) {
|
1313
1309
|
const subSchema = def.definitions[key];
|
1314
1310
|
const model = kotlinTypeFromSchema(subSchema, {
|
1315
|
-
|
1311
|
+
typePrefix: context.typePrefix,
|
1316
1312
|
clientName: context.clientName,
|
1317
1313
|
clientVersion: context.clientVersion,
|
1318
1314
|
instancePath: `/${key}`,
|
@@ -1644,62 +1640,89 @@ private suspend fun __prepareRequest(
|
|
1644
1640
|
return client.prepareRequest(builder)
|
1645
1641
|
}
|
1646
1642
|
|
1647
|
-
|
1648
|
-
|
1649
|
-
|
1650
|
-
|
1651
|
-
|
1652
|
-
|
1653
|
-
|
1654
|
-
|
1655
|
-
|
1656
|
-
|
1657
|
-
|
1658
|
-
|
1659
|
-
|
1660
|
-
|
1661
|
-
|
1662
|
-
|
1663
|
-
|
1664
|
-
|
1643
|
+
// SSE_FN_START
|
1644
|
+
private enum class SseEventLineType {
|
1645
|
+
Id,
|
1646
|
+
Event,
|
1647
|
+
Data,
|
1648
|
+
Retry,
|
1649
|
+
None,
|
1650
|
+
}
|
1651
|
+
|
1652
|
+
private fun __parseSseEventLine(line: String): Pair<SseEventLineType, String> {
|
1653
|
+
if (line.startsWith("id:")) {
|
1654
|
+
return Pair(SseEventLineType.Id, line.substring(3).trim())
|
1655
|
+
}
|
1656
|
+
if (line.startsWith("event:")) {
|
1657
|
+
return Pair(SseEventLineType.Event, line.substring(6).trim())
|
1658
|
+
}
|
1659
|
+
if (line.startsWith("data:")) {
|
1660
|
+
return Pair(SseEventLineType.Data, line.substring(5).trim())
|
1661
|
+
}
|
1662
|
+
if (line.startsWith("retry:")) {
|
1663
|
+
return Pair(SseEventLineType.Retry, line.substring(6).trim())
|
1665
1664
|
}
|
1666
|
-
return
|
1665
|
+
return Pair(SseEventLineType.None, "")
|
1667
1666
|
}
|
1668
1667
|
|
1669
|
-
private class __SseEvent(
|
1668
|
+
private data class __SseEvent(
|
1669
|
+
val id: String? = null,
|
1670
|
+
val event: String,
|
1671
|
+
val data: String,
|
1672
|
+
val retry: Int? = null
|
1673
|
+
)
|
1670
1674
|
|
1671
1675
|
private class __SseEventParsingResult(val events: List<__SseEvent>, val leftover: String)
|
1672
1676
|
|
1673
1677
|
private fun __parseSseEvents(input: String): __SseEventParsingResult {
|
1674
|
-
val inputs = input.split("\\n\\n").toMutableList()
|
1675
|
-
if (inputs.isEmpty()) {
|
1676
|
-
return __SseEventParsingResult(
|
1677
|
-
events = listOf(),
|
1678
|
-
leftover = "",
|
1679
|
-
)
|
1680
|
-
}
|
1681
|
-
if (inputs.size == 1) {
|
1682
|
-
return __SseEventParsingResult(
|
1683
|
-
events = listOf(),
|
1684
|
-
leftover = inputs.last(),
|
1685
|
-
)
|
1686
|
-
}
|
1687
|
-
val leftover = inputs.last()
|
1688
|
-
inputs.removeLast()
|
1689
1678
|
val events = mutableListOf<__SseEvent>()
|
1690
|
-
|
1691
|
-
|
1692
|
-
|
1679
|
+
val lines = input.lines()
|
1680
|
+
if (lines.isEmpty()) {
|
1681
|
+
return __SseEventParsingResult(events = listOf(), leftover = "")
|
1682
|
+
}
|
1683
|
+
var id: String? = null
|
1684
|
+
var event: String? = null
|
1685
|
+
var data: String? = null
|
1686
|
+
var retry: Int? = null
|
1687
|
+
var lastIndex: Int? = 0
|
1688
|
+
lines.forEachIndexed { index, line ->
|
1689
|
+
if (line.isNotEmpty()) {
|
1690
|
+
val (type, value) = __parseSseEventLine(line)
|
1691
|
+
when (type) {
|
1692
|
+
SseEventLineType.Id -> id = value
|
1693
|
+
SseEventLineType.Event -> event = value
|
1694
|
+
SseEventLineType.Data -> data = value
|
1695
|
+
SseEventLineType.Retry -> retry = value.toInt()
|
1696
|
+
SseEventLineType.None -> {}
|
1697
|
+
}
|
1698
|
+
}
|
1699
|
+
val isEnd = line == ""
|
1700
|
+
if (isEnd) {
|
1701
|
+
if (data != null) {
|
1702
|
+
events.add(
|
1703
|
+
__SseEvent(
|
1704
|
+
id = id,
|
1705
|
+
event = event ?: "message",
|
1706
|
+
data = data!!,
|
1707
|
+
retry = retry,
|
1708
|
+
)
|
1709
|
+
)
|
1710
|
+
}
|
1711
|
+
id = null
|
1712
|
+
event = null
|
1713
|
+
data = null
|
1714
|
+
retry = null
|
1715
|
+
lastIndex = if (index + 1 < lines.size) index + 1 else null
|
1693
1716
|
}
|
1694
1717
|
}
|
1695
1718
|
return __SseEventParsingResult(
|
1696
1719
|
events = events,
|
1697
|
-
leftover =
|
1720
|
+
leftover = if (lastIndex != null) lines.subList(lastIndex!!, lines.size).joinToString(separator = "\\n") else ""
|
1698
1721
|
)
|
1699
1722
|
}
|
1723
|
+
// SSE_FN_END
|
1700
1724
|
|
1701
1725
|
private suspend fun __handleSseRequest(
|
1702
|
-
scope: CoroutineScope,
|
1703
1726
|
httpClient: HttpClient,
|
1704
1727
|
url: String,
|
1705
1728
|
method: HttpMethod,
|
@@ -1710,16 +1733,16 @@ private suspend fun __handleSseRequest(
|
|
1710
1733
|
lastEventId: String?,
|
1711
1734
|
onOpen: ((response: HttpResponse) -> Unit) = {},
|
1712
1735
|
onClose: (() -> Unit) = {},
|
1713
|
-
onError: ((error: ${clientName}Error) -> Unit) = {},
|
1714
1736
|
onData: ((data: String) -> Unit) = {},
|
1715
|
-
|
1737
|
+
onRequestError: ((error: Exception) -> Unit) = {},
|
1738
|
+
onResponseError: ((error: ${clientName}Error) -> Unit) = {},
|
1716
1739
|
bufferCapacity: Int,
|
1717
1740
|
) {
|
1718
1741
|
val finalHeaders = headers?.invoke() ?: mutableMapOf()
|
1719
1742
|
var lastId = lastEventId
|
1720
1743
|
// exponential backoff maxing out at 32 seconds
|
1721
1744
|
if (backoffTime > 0) {
|
1722
|
-
withContext(
|
1745
|
+
withContext(currentCoroutineContext()) {
|
1723
1746
|
Thread.sleep(backoffTime)
|
1724
1747
|
}
|
1725
1748
|
}
|
@@ -1741,16 +1764,17 @@ private suspend fun __handleSseRequest(
|
|
1741
1764
|
onOpen(httpResponse)
|
1742
1765
|
} catch (e: CancellationException) {
|
1743
1766
|
onClose()
|
1767
|
+
httpResponse.cancel()
|
1744
1768
|
return@execute
|
1745
1769
|
}
|
1746
1770
|
if (httpResponse.status.value !in 200..299) {
|
1747
1771
|
try {
|
1748
1772
|
if (httpResponse.headers["Content-Type"] == "application/json") {
|
1749
|
-
|
1773
|
+
onResponseError(
|
1750
1774
|
${clientName}Error.fromJson(httpResponse.bodyAsText())
|
1751
1775
|
)
|
1752
1776
|
} else {
|
1753
|
-
|
1777
|
+
onResponseError(
|
1754
1778
|
${clientName}Error(
|
1755
1779
|
code = httpResponse.status.value,
|
1756
1780
|
errorMessage = httpResponse.status.description,
|
@@ -1761,10 +1785,10 @@ private suspend fun __handleSseRequest(
|
|
1761
1785
|
}
|
1762
1786
|
} catch (e: CancellationException) {
|
1763
1787
|
onClose()
|
1788
|
+
httpResponse.cancel()
|
1764
1789
|
return@execute
|
1765
1790
|
}
|
1766
|
-
__handleSseRequest(
|
1767
|
-
scope = scope,
|
1791
|
+
return@execute __handleSseRequest(
|
1768
1792
|
httpClient = httpClient,
|
1769
1793
|
url = url,
|
1770
1794
|
method = method,
|
@@ -1776,15 +1800,13 @@ private suspend fun __handleSseRequest(
|
|
1776
1800
|
bufferCapacity = bufferCapacity,
|
1777
1801
|
onOpen = onOpen,
|
1778
1802
|
onClose = onClose,
|
1779
|
-
onError = onError,
|
1780
1803
|
onData = onData,
|
1781
|
-
|
1804
|
+
onResponseError = onResponseError,
|
1782
1805
|
)
|
1783
|
-
return@execute
|
1784
1806
|
}
|
1785
1807
|
if (httpResponse.headers["Content-Type"] != "text/event-stream") {
|
1786
1808
|
try {
|
1787
|
-
|
1809
|
+
onResponseError(
|
1788
1810
|
${clientName}Error(
|
1789
1811
|
code = 0,
|
1790
1812
|
errorMessage = "Expected server to return Content-Type \\"text/event-stream\\". Got \\"\${httpResponse.headers["Content-Type"]}\\"",
|
@@ -1793,10 +1815,10 @@ private suspend fun __handleSseRequest(
|
|
1793
1815
|
)
|
1794
1816
|
)
|
1795
1817
|
} catch (e: CancellationException) {
|
1818
|
+
httpResponse.cancel()
|
1796
1819
|
return@execute
|
1797
1820
|
}
|
1798
|
-
__handleSseRequest(
|
1799
|
-
scope = scope,
|
1821
|
+
return@execute __handleSseRequest(
|
1800
1822
|
httpClient = httpClient,
|
1801
1823
|
url = url,
|
1802
1824
|
method = method,
|
@@ -1808,14 +1830,12 @@ private suspend fun __handleSseRequest(
|
|
1808
1830
|
bufferCapacity = bufferCapacity,
|
1809
1831
|
onOpen = onOpen,
|
1810
1832
|
onClose = onClose,
|
1811
|
-
onError = onError,
|
1812
1833
|
onData = onData,
|
1813
|
-
|
1834
|
+
onResponseError = onResponseError,
|
1814
1835
|
)
|
1815
|
-
return@execute
|
1816
1836
|
}
|
1817
1837
|
newBackoffTime = 0
|
1818
|
-
val channel: ByteReadChannel = httpResponse.
|
1838
|
+
val channel: ByteReadChannel = httpResponse.body()
|
1819
1839
|
var pendingData = ""
|
1820
1840
|
while (!channel.isClosedForRead) {
|
1821
1841
|
val buffer = ByteBuffer.allocateDirect(bufferCapacity)
|
@@ -1835,6 +1855,7 @@ private suspend fun __handleSseRequest(
|
|
1835
1855
|
onData(event.data)
|
1836
1856
|
} catch (e: CancellationException) {
|
1837
1857
|
onClose()
|
1858
|
+
httpResponse.cancel()
|
1838
1859
|
return@execute
|
1839
1860
|
}
|
1840
1861
|
}
|
@@ -1844,22 +1865,11 @@ private suspend fun __handleSseRequest(
|
|
1844
1865
|
return@execute
|
1845
1866
|
}
|
1846
1867
|
|
1847
|
-
"error" -> {
|
1848
|
-
val error = ${clientName}Error.fromJson(event.data)
|
1849
|
-
try {
|
1850
|
-
onError(error)
|
1851
|
-
} catch (e: CancellationException) {
|
1852
|
-
onClose()
|
1853
|
-
return@execute
|
1854
|
-
}
|
1855
|
-
}
|
1856
|
-
|
1857
1868
|
else -> {}
|
1858
1869
|
}
|
1859
1870
|
}
|
1860
1871
|
}
|
1861
|
-
__handleSseRequest(
|
1862
|
-
scope = scope,
|
1872
|
+
return@execute __handleSseRequest(
|
1863
1873
|
httpClient = httpClient,
|
1864
1874
|
url = url,
|
1865
1875
|
method = method,
|
@@ -1871,22 +1881,13 @@ private suspend fun __handleSseRequest(
|
|
1871
1881
|
bufferCapacity = bufferCapacity,
|
1872
1882
|
onOpen = onOpen,
|
1873
1883
|
onClose = onClose,
|
1874
|
-
onError = onError,
|
1875
1884
|
onData = onData,
|
1876
|
-
|
1885
|
+
onResponseError = onResponseError,
|
1877
1886
|
)
|
1878
1887
|
}
|
1879
1888
|
} catch (e: java.net.ConnectException) {
|
1880
|
-
|
1881
|
-
|
1882
|
-
code = 503,
|
1883
|
-
errorMessage = if (e.message != null) e.message!! else "Error connecting to $url",
|
1884
|
-
data = JsonPrimitive(e.toString()),
|
1885
|
-
stack = e.stackTraceToString().split("\\n"),
|
1886
|
-
)
|
1887
|
-
)
|
1888
|
-
__handleSseRequest(
|
1889
|
-
scope = scope,
|
1889
|
+
onRequestError(e)
|
1890
|
+
return __handleSseRequest(
|
1890
1891
|
httpClient = httpClient,
|
1891
1892
|
url = url,
|
1892
1893
|
method = method,
|
@@ -1898,14 +1899,12 @@ private suspend fun __handleSseRequest(
|
|
1898
1899
|
bufferCapacity = bufferCapacity,
|
1899
1900
|
onOpen = onOpen,
|
1900
1901
|
onClose = onClose,
|
1901
|
-
onError = onError,
|
1902
1902
|
onData = onData,
|
1903
|
-
|
1903
|
+
onResponseError = onResponseError,
|
1904
1904
|
)
|
1905
|
-
return
|
1906
1905
|
} catch (e: Exception) {
|
1907
|
-
|
1908
|
-
|
1906
|
+
onRequestError(e)
|
1907
|
+
return __handleSseRequest(
|
1909
1908
|
httpClient = httpClient,
|
1910
1909
|
url = url,
|
1911
1910
|
method = method,
|
@@ -1917,9 +1916,8 @@ private suspend fun __handleSseRequest(
|
|
1917
1916
|
bufferCapacity = bufferCapacity,
|
1918
1917
|
onOpen = onOpen,
|
1919
1918
|
onClose = onClose,
|
1920
|
-
onError = onError,
|
1921
1919
|
onData = onData,
|
1922
|
-
|
1920
|
+
onResponseError = onResponseError,
|
1923
1921
|
)
|
1924
1922
|
}
|
1925
1923
|
}`;
|
@@ -1932,14 +1930,14 @@ function getHeader(options) {
|
|
1932
1930
|
)
|
1933
1931
|
|
1934
1932
|
import io.ktor.client.*
|
1933
|
+
import io.ktor.client.call.*
|
1935
1934
|
import io.ktor.client.plugins.*
|
1936
1935
|
import io.ktor.client.request.*
|
1937
1936
|
import io.ktor.client.statement.*
|
1938
1937
|
import io.ktor.http.*
|
1939
1938
|
import io.ktor.utils.io.*
|
1940
|
-
import kotlinx.coroutines.
|
1941
|
-
import kotlinx.coroutines.
|
1942
|
-
import kotlinx.coroutines.launch
|
1939
|
+
import kotlinx.coroutines.cancel
|
1940
|
+
import kotlinx.coroutines.currentCoroutineContext
|
1943
1941
|
import kotlinx.coroutines.withContext
|
1944
1942
|
import kotlinx.serialization.encodeToString
|
1945
1943
|
import kotlinx.serialization.json.*
|
package/dist/index.d.cts
CHANGED
@@ -2,7 +2,7 @@ import * as _arrirpc_codegen_utils from '@arrirpc/codegen-utils';
|
|
2
2
|
import { AppDefinition, Schema } from '@arrirpc/codegen-utils';
|
3
3
|
|
4
4
|
interface CodegenContext {
|
5
|
-
|
5
|
+
typePrefix: string;
|
6
6
|
clientName: string;
|
7
7
|
clientVersion: string;
|
8
8
|
instancePath: string;
|
@@ -25,12 +25,12 @@ interface KotlinProperty {
|
|
25
25
|
|
26
26
|
interface ServiceContext {
|
27
27
|
clientName: string;
|
28
|
-
|
28
|
+
typePrefix?: string;
|
29
29
|
modelJsonInstances: Record<string, string>;
|
30
30
|
}
|
31
31
|
interface KotlinClientOptions {
|
32
32
|
clientName?: string;
|
33
|
-
|
33
|
+
typePrefix?: string;
|
34
34
|
outputFile: string;
|
35
35
|
}
|
36
36
|
declare const kotlinClientGenerator: _arrirpc_codegen_utils.GeneratorPlugin<KotlinClientOptions>;
|
package/dist/index.d.mts
CHANGED
@@ -2,7 +2,7 @@ import * as _arrirpc_codegen_utils from '@arrirpc/codegen-utils';
|
|
2
2
|
import { AppDefinition, Schema } from '@arrirpc/codegen-utils';
|
3
3
|
|
4
4
|
interface CodegenContext {
|
5
|
-
|
5
|
+
typePrefix: string;
|
6
6
|
clientName: string;
|
7
7
|
clientVersion: string;
|
8
8
|
instancePath: string;
|
@@ -25,12 +25,12 @@ interface KotlinProperty {
|
|
25
25
|
|
26
26
|
interface ServiceContext {
|
27
27
|
clientName: string;
|
28
|
-
|
28
|
+
typePrefix?: string;
|
29
29
|
modelJsonInstances: Record<string, string>;
|
30
30
|
}
|
31
31
|
interface KotlinClientOptions {
|
32
32
|
clientName?: string;
|
33
|
-
|
33
|
+
typePrefix?: string;
|
34
34
|
outputFile: string;
|
35
35
|
}
|
36
36
|
declare const kotlinClientGenerator: _arrirpc_codegen_utils.GeneratorPlugin<KotlinClientOptions>;
|
package/dist/index.d.ts
CHANGED
@@ -2,7 +2,7 @@ import * as _arrirpc_codegen_utils from '@arrirpc/codegen-utils';
|
|
2
2
|
import { AppDefinition, Schema } from '@arrirpc/codegen-utils';
|
3
3
|
|
4
4
|
interface CodegenContext {
|
5
|
-
|
5
|
+
typePrefix: string;
|
6
6
|
clientName: string;
|
7
7
|
clientVersion: string;
|
8
8
|
instancePath: string;
|
@@ -25,12 +25,12 @@ interface KotlinProperty {
|
|
25
25
|
|
26
26
|
interface ServiceContext {
|
27
27
|
clientName: string;
|
28
|
-
|
28
|
+
typePrefix?: string;
|
29
29
|
modelJsonInstances: Record<string, string>;
|
30
30
|
}
|
31
31
|
interface KotlinClientOptions {
|
32
32
|
clientName?: string;
|
33
|
-
|
33
|
+
typePrefix?: string;
|
34
34
|
outputFile: string;
|
35
35
|
}
|
36
36
|
declare const kotlinClientGenerator: _arrirpc_codegen_utils.GeneratorPlugin<KotlinClientOptions>;
|
package/dist/index.mjs
CHANGED
@@ -59,7 +59,7 @@ function getClassName(schema, context) {
|
|
59
59
|
normalize: true
|
60
60
|
})
|
61
61
|
);
|
62
|
-
return `${context.
|
62
|
+
return `${context.typePrefix}${className2}`;
|
63
63
|
}
|
64
64
|
const depth = instanceDepth(context);
|
65
65
|
if (depth === 1 && !context.discriminatorKey) {
|
@@ -68,7 +68,7 @@ function getClassName(schema, context) {
|
|
68
68
|
normalize: true
|
69
69
|
})
|
70
70
|
);
|
71
|
-
return `${context.
|
71
|
+
return `${context.typePrefix}${className2}`;
|
72
72
|
}
|
73
73
|
if (context.discriminatorParentId && context.discriminatorKey && context.discriminatorValue) {
|
74
74
|
const className2 = kotlinClassName(
|
@@ -77,7 +77,7 @@ function getClassName(schema, context) {
|
|
77
77
|
{ normalize: true }
|
78
78
|
)
|
79
79
|
);
|
80
|
-
return `${context.
|
80
|
+
return `${context.typePrefix}${className2}`;
|
81
81
|
}
|
82
82
|
const className = kotlinClassName(
|
83
83
|
pascalCase(
|
@@ -87,7 +87,7 @@ function getClassName(schema, context) {
|
|
87
87
|
}
|
88
88
|
)
|
89
89
|
);
|
90
|
-
return `${context.
|
90
|
+
return `${context.typePrefix}${className}`;
|
91
91
|
}
|
92
92
|
function instanceDepth(context) {
|
93
93
|
const parts = context.instancePath.split("/");
|
@@ -166,7 +166,7 @@ function kotlinArrayFromSchema(schema, context) {
|
|
166
166
|
const nullable = isNullable(schema, context);
|
167
167
|
const defaultValue = nullable ? "null" : "mutableListOf()";
|
168
168
|
const subType = kotlinTypeFromSchema(schema.elements, {
|
169
|
-
|
169
|
+
typePrefix: context.typePrefix,
|
170
170
|
clientName: context.clientName,
|
171
171
|
clientVersion: context.clientVersion,
|
172
172
|
instancePath: `${context.instancePath}/[Element]`,
|
@@ -307,7 +307,7 @@ function kotlinObjectFromSchema(schema, context) {
|
|
307
307
|
kotlinKeys.push(kotlinKey);
|
308
308
|
const prop = schema.properties[key];
|
309
309
|
const type = kotlinTypeFromSchema(prop, {
|
310
|
-
|
310
|
+
typePrefix: context.typePrefix,
|
311
311
|
clientName: context.clientName,
|
312
312
|
clientVersion: context.clientVersion,
|
313
313
|
instancePath: `/${className}/${key}`,
|
@@ -341,7 +341,7 @@ function kotlinObjectFromSchema(schema, context) {
|
|
341
341
|
const kotlinKey = kotlinIdentifier(key);
|
342
342
|
kotlinKeys.push(kotlinKey);
|
343
343
|
const type = kotlinTypeFromSchema(schema.optionalProperties[key], {
|
344
|
-
|
344
|
+
typePrefix: context.typePrefix,
|
345
345
|
clientName: context.clientName,
|
346
346
|
clientVersion: context.clientVersion,
|
347
347
|
instancePath: `/${className}/${key}`,
|
@@ -440,7 +440,7 @@ function kotlinDiscriminatorFromSchema(schema, context) {
|
|
440
440
|
for (const key of Object.keys(schema.mapping)) {
|
441
441
|
const subSchema = schema.mapping[key];
|
442
442
|
const subType = kotlinObjectFromSchema(subSchema, {
|
443
|
-
|
443
|
+
typePrefix: context.typePrefix,
|
444
444
|
clientName: context.clientName,
|
445
445
|
clientVersion: context.clientVersion,
|
446
446
|
instancePath: context.instancePath,
|
@@ -628,7 +628,7 @@ function kotlinEnumFromSchema(schema, context) {
|
|
628
628
|
function kotlinMapFromSchema(schema, context) {
|
629
629
|
const nullable = isNullable(schema, context);
|
630
630
|
const subType = kotlinTypeFromSchema(schema.values, {
|
631
|
-
|
631
|
+
typePrefix: context.typePrefix,
|
632
632
|
clientName: context.clientName,
|
633
633
|
clientVersion: context.clientVersion,
|
634
634
|
instancePath: `${context.instancePath}/[value]`,
|
@@ -1123,8 +1123,8 @@ function kotlinProcedureFromSchema(schema, context) {
|
|
1123
1123
|
}
|
1124
1124
|
function kotlinHttpRpcFromSchema(schema, context) {
|
1125
1125
|
const name = getProcedureName(context);
|
1126
|
-
const params = schema.params ? kotlinClassName(`${context.
|
1127
|
-
const response = schema.response ? kotlinClassName(`${context.
|
1126
|
+
const params = schema.params ? kotlinClassName(`${context.typePrefix}_${schema.params}`) : void 0;
|
1127
|
+
const response = schema.response ? kotlinClassName(`${context.typePrefix}_${schema.response}`) : void 0;
|
1128
1128
|
const codeComment = getCodeComment(
|
1129
1129
|
{
|
1130
1130
|
description: schema.description,
|
@@ -1134,40 +1134,36 @@ function kotlinHttpRpcFromSchema(schema, context) {
|
|
1134
1134
|
"method"
|
1135
1135
|
);
|
1136
1136
|
if (schema.isEventStream) {
|
1137
|
-
return `${codeComment}fun ${name}(
|
1138
|
-
scope: CoroutineScope,
|
1137
|
+
return `${codeComment}suspend fun ${name}(
|
1139
1138
|
${params ? `params: ${params},` : ""}
|
1140
1139
|
lastEventId: String? = null,
|
1141
|
-
bufferCapacity: Int = 1024,
|
1140
|
+
bufferCapacity: Int = 1024 * 1024,
|
1142
1141
|
onOpen: ((response: HttpResponse) -> Unit) = {},
|
1143
1142
|
onClose: (() -> Unit) = {},
|
1144
|
-
|
1145
|
-
|
1143
|
+
onRequestError: ((error: Exception) -> Unit) = {},
|
1144
|
+
onResponseError: ((error: ${context.clientName}Error) -> Unit) = {},
|
1146
1145
|
onData: ((${response ? `data: ${response}` : ""}) -> Unit) = {},
|
1147
|
-
|
1148
|
-
|
1149
|
-
|
1150
|
-
|
1151
|
-
|
1152
|
-
|
1153
|
-
|
1154
|
-
|
1155
|
-
|
1156
|
-
|
1157
|
-
|
1158
|
-
|
1159
|
-
|
1160
|
-
|
1161
|
-
|
1162
|
-
|
1163
|
-
|
1164
|
-
|
1165
|
-
|
1166
|
-
|
1167
|
-
|
1168
|
-
)
|
1169
|
-
}
|
1170
|
-
return job
|
1146
|
+
maxBackoffTime: Long? = null,
|
1147
|
+
): Unit {
|
1148
|
+
__handleSseRequest(
|
1149
|
+
httpClient = httpClient,
|
1150
|
+
url = "$baseUrl${schema.path}",
|
1151
|
+
method = HttpMethod.${pascalCase(schema.method, { normalize: true })},
|
1152
|
+
params = ${params ? "params" : "null"},
|
1153
|
+
headers = headers,
|
1154
|
+
backoffTime = 0,
|
1155
|
+
maxBackoffTime = maxBackoffTime ?: 30000L,
|
1156
|
+
lastEventId = lastEventId,
|
1157
|
+
bufferCapacity = bufferCapacity,
|
1158
|
+
onOpen = onOpen,
|
1159
|
+
onClose = onClose,
|
1160
|
+
onRequestError = onRequestError,
|
1161
|
+
onResponseError = onResponseError,
|
1162
|
+
onData = { str ->
|
1163
|
+
${response ? `val data = ${response}.fromJson(str)` : ""}
|
1164
|
+
onData(${response ? "data" : ""})
|
1165
|
+
}
|
1166
|
+
)
|
1171
1167
|
}`;
|
1172
1168
|
}
|
1173
1169
|
const headingCheck = `if (response.headers["Content-Type"] != "application/json") {
|
@@ -1295,7 +1291,7 @@ const kotlinClientGenerator = defineGeneratorPlugin(
|
|
1295
1291
|
function kotlinClientFromAppDefinition(def, options) {
|
1296
1292
|
const clientName = kotlinClassName(options.clientName ?? "Client");
|
1297
1293
|
const context = {
|
1298
|
-
|
1294
|
+
typePrefix: options.typePrefix ?? "",
|
1299
1295
|
clientName,
|
1300
1296
|
clientVersion: def.info?.version ?? "",
|
1301
1297
|
instancePath: "",
|
@@ -1306,7 +1302,7 @@ function kotlinClientFromAppDefinition(def, options) {
|
|
1306
1302
|
for (const key of Object.keys(def.definitions)) {
|
1307
1303
|
const subSchema = def.definitions[key];
|
1308
1304
|
const model = kotlinTypeFromSchema(subSchema, {
|
1309
|
-
|
1305
|
+
typePrefix: context.typePrefix,
|
1310
1306
|
clientName: context.clientName,
|
1311
1307
|
clientVersion: context.clientVersion,
|
1312
1308
|
instancePath: `/${key}`,
|
@@ -1638,62 +1634,89 @@ private suspend fun __prepareRequest(
|
|
1638
1634
|
return client.prepareRequest(builder)
|
1639
1635
|
}
|
1640
1636
|
|
1641
|
-
|
1642
|
-
|
1643
|
-
|
1644
|
-
|
1645
|
-
|
1646
|
-
|
1647
|
-
|
1648
|
-
|
1649
|
-
|
1650
|
-
|
1651
|
-
|
1652
|
-
|
1653
|
-
|
1654
|
-
|
1655
|
-
|
1656
|
-
|
1657
|
-
|
1658
|
-
|
1637
|
+
// SSE_FN_START
|
1638
|
+
private enum class SseEventLineType {
|
1639
|
+
Id,
|
1640
|
+
Event,
|
1641
|
+
Data,
|
1642
|
+
Retry,
|
1643
|
+
None,
|
1644
|
+
}
|
1645
|
+
|
1646
|
+
private fun __parseSseEventLine(line: String): Pair<SseEventLineType, String> {
|
1647
|
+
if (line.startsWith("id:")) {
|
1648
|
+
return Pair(SseEventLineType.Id, line.substring(3).trim())
|
1649
|
+
}
|
1650
|
+
if (line.startsWith("event:")) {
|
1651
|
+
return Pair(SseEventLineType.Event, line.substring(6).trim())
|
1652
|
+
}
|
1653
|
+
if (line.startsWith("data:")) {
|
1654
|
+
return Pair(SseEventLineType.Data, line.substring(5).trim())
|
1655
|
+
}
|
1656
|
+
if (line.startsWith("retry:")) {
|
1657
|
+
return Pair(SseEventLineType.Retry, line.substring(6).trim())
|
1659
1658
|
}
|
1660
|
-
return
|
1659
|
+
return Pair(SseEventLineType.None, "")
|
1661
1660
|
}
|
1662
1661
|
|
1663
|
-
private class __SseEvent(
|
1662
|
+
private data class __SseEvent(
|
1663
|
+
val id: String? = null,
|
1664
|
+
val event: String,
|
1665
|
+
val data: String,
|
1666
|
+
val retry: Int? = null
|
1667
|
+
)
|
1664
1668
|
|
1665
1669
|
private class __SseEventParsingResult(val events: List<__SseEvent>, val leftover: String)
|
1666
1670
|
|
1667
1671
|
private fun __parseSseEvents(input: String): __SseEventParsingResult {
|
1668
|
-
val inputs = input.split("\\n\\n").toMutableList()
|
1669
|
-
if (inputs.isEmpty()) {
|
1670
|
-
return __SseEventParsingResult(
|
1671
|
-
events = listOf(),
|
1672
|
-
leftover = "",
|
1673
|
-
)
|
1674
|
-
}
|
1675
|
-
if (inputs.size == 1) {
|
1676
|
-
return __SseEventParsingResult(
|
1677
|
-
events = listOf(),
|
1678
|
-
leftover = inputs.last(),
|
1679
|
-
)
|
1680
|
-
}
|
1681
|
-
val leftover = inputs.last()
|
1682
|
-
inputs.removeLast()
|
1683
1672
|
val events = mutableListOf<__SseEvent>()
|
1684
|
-
|
1685
|
-
|
1686
|
-
|
1673
|
+
val lines = input.lines()
|
1674
|
+
if (lines.isEmpty()) {
|
1675
|
+
return __SseEventParsingResult(events = listOf(), leftover = "")
|
1676
|
+
}
|
1677
|
+
var id: String? = null
|
1678
|
+
var event: String? = null
|
1679
|
+
var data: String? = null
|
1680
|
+
var retry: Int? = null
|
1681
|
+
var lastIndex: Int? = 0
|
1682
|
+
lines.forEachIndexed { index, line ->
|
1683
|
+
if (line.isNotEmpty()) {
|
1684
|
+
val (type, value) = __parseSseEventLine(line)
|
1685
|
+
when (type) {
|
1686
|
+
SseEventLineType.Id -> id = value
|
1687
|
+
SseEventLineType.Event -> event = value
|
1688
|
+
SseEventLineType.Data -> data = value
|
1689
|
+
SseEventLineType.Retry -> retry = value.toInt()
|
1690
|
+
SseEventLineType.None -> {}
|
1691
|
+
}
|
1692
|
+
}
|
1693
|
+
val isEnd = line == ""
|
1694
|
+
if (isEnd) {
|
1695
|
+
if (data != null) {
|
1696
|
+
events.add(
|
1697
|
+
__SseEvent(
|
1698
|
+
id = id,
|
1699
|
+
event = event ?: "message",
|
1700
|
+
data = data!!,
|
1701
|
+
retry = retry,
|
1702
|
+
)
|
1703
|
+
)
|
1704
|
+
}
|
1705
|
+
id = null
|
1706
|
+
event = null
|
1707
|
+
data = null
|
1708
|
+
retry = null
|
1709
|
+
lastIndex = if (index + 1 < lines.size) index + 1 else null
|
1687
1710
|
}
|
1688
1711
|
}
|
1689
1712
|
return __SseEventParsingResult(
|
1690
1713
|
events = events,
|
1691
|
-
leftover =
|
1714
|
+
leftover = if (lastIndex != null) lines.subList(lastIndex!!, lines.size).joinToString(separator = "\\n") else ""
|
1692
1715
|
)
|
1693
1716
|
}
|
1717
|
+
// SSE_FN_END
|
1694
1718
|
|
1695
1719
|
private suspend fun __handleSseRequest(
|
1696
|
-
scope: CoroutineScope,
|
1697
1720
|
httpClient: HttpClient,
|
1698
1721
|
url: String,
|
1699
1722
|
method: HttpMethod,
|
@@ -1704,16 +1727,16 @@ private suspend fun __handleSseRequest(
|
|
1704
1727
|
lastEventId: String?,
|
1705
1728
|
onOpen: ((response: HttpResponse) -> Unit) = {},
|
1706
1729
|
onClose: (() -> Unit) = {},
|
1707
|
-
onError: ((error: ${clientName}Error) -> Unit) = {},
|
1708
1730
|
onData: ((data: String) -> Unit) = {},
|
1709
|
-
|
1731
|
+
onRequestError: ((error: Exception) -> Unit) = {},
|
1732
|
+
onResponseError: ((error: ${clientName}Error) -> Unit) = {},
|
1710
1733
|
bufferCapacity: Int,
|
1711
1734
|
) {
|
1712
1735
|
val finalHeaders = headers?.invoke() ?: mutableMapOf()
|
1713
1736
|
var lastId = lastEventId
|
1714
1737
|
// exponential backoff maxing out at 32 seconds
|
1715
1738
|
if (backoffTime > 0) {
|
1716
|
-
withContext(
|
1739
|
+
withContext(currentCoroutineContext()) {
|
1717
1740
|
Thread.sleep(backoffTime)
|
1718
1741
|
}
|
1719
1742
|
}
|
@@ -1735,16 +1758,17 @@ private suspend fun __handleSseRequest(
|
|
1735
1758
|
onOpen(httpResponse)
|
1736
1759
|
} catch (e: CancellationException) {
|
1737
1760
|
onClose()
|
1761
|
+
httpResponse.cancel()
|
1738
1762
|
return@execute
|
1739
1763
|
}
|
1740
1764
|
if (httpResponse.status.value !in 200..299) {
|
1741
1765
|
try {
|
1742
1766
|
if (httpResponse.headers["Content-Type"] == "application/json") {
|
1743
|
-
|
1767
|
+
onResponseError(
|
1744
1768
|
${clientName}Error.fromJson(httpResponse.bodyAsText())
|
1745
1769
|
)
|
1746
1770
|
} else {
|
1747
|
-
|
1771
|
+
onResponseError(
|
1748
1772
|
${clientName}Error(
|
1749
1773
|
code = httpResponse.status.value,
|
1750
1774
|
errorMessage = httpResponse.status.description,
|
@@ -1755,10 +1779,10 @@ private suspend fun __handleSseRequest(
|
|
1755
1779
|
}
|
1756
1780
|
} catch (e: CancellationException) {
|
1757
1781
|
onClose()
|
1782
|
+
httpResponse.cancel()
|
1758
1783
|
return@execute
|
1759
1784
|
}
|
1760
|
-
__handleSseRequest(
|
1761
|
-
scope = scope,
|
1785
|
+
return@execute __handleSseRequest(
|
1762
1786
|
httpClient = httpClient,
|
1763
1787
|
url = url,
|
1764
1788
|
method = method,
|
@@ -1770,15 +1794,13 @@ private suspend fun __handleSseRequest(
|
|
1770
1794
|
bufferCapacity = bufferCapacity,
|
1771
1795
|
onOpen = onOpen,
|
1772
1796
|
onClose = onClose,
|
1773
|
-
onError = onError,
|
1774
1797
|
onData = onData,
|
1775
|
-
|
1798
|
+
onResponseError = onResponseError,
|
1776
1799
|
)
|
1777
|
-
return@execute
|
1778
1800
|
}
|
1779
1801
|
if (httpResponse.headers["Content-Type"] != "text/event-stream") {
|
1780
1802
|
try {
|
1781
|
-
|
1803
|
+
onResponseError(
|
1782
1804
|
${clientName}Error(
|
1783
1805
|
code = 0,
|
1784
1806
|
errorMessage = "Expected server to return Content-Type \\"text/event-stream\\". Got \\"\${httpResponse.headers["Content-Type"]}\\"",
|
@@ -1787,10 +1809,10 @@ private suspend fun __handleSseRequest(
|
|
1787
1809
|
)
|
1788
1810
|
)
|
1789
1811
|
} catch (e: CancellationException) {
|
1812
|
+
httpResponse.cancel()
|
1790
1813
|
return@execute
|
1791
1814
|
}
|
1792
|
-
__handleSseRequest(
|
1793
|
-
scope = scope,
|
1815
|
+
return@execute __handleSseRequest(
|
1794
1816
|
httpClient = httpClient,
|
1795
1817
|
url = url,
|
1796
1818
|
method = method,
|
@@ -1802,14 +1824,12 @@ private suspend fun __handleSseRequest(
|
|
1802
1824
|
bufferCapacity = bufferCapacity,
|
1803
1825
|
onOpen = onOpen,
|
1804
1826
|
onClose = onClose,
|
1805
|
-
onError = onError,
|
1806
1827
|
onData = onData,
|
1807
|
-
|
1828
|
+
onResponseError = onResponseError,
|
1808
1829
|
)
|
1809
|
-
return@execute
|
1810
1830
|
}
|
1811
1831
|
newBackoffTime = 0
|
1812
|
-
val channel: ByteReadChannel = httpResponse.
|
1832
|
+
val channel: ByteReadChannel = httpResponse.body()
|
1813
1833
|
var pendingData = ""
|
1814
1834
|
while (!channel.isClosedForRead) {
|
1815
1835
|
val buffer = ByteBuffer.allocateDirect(bufferCapacity)
|
@@ -1829,6 +1849,7 @@ private suspend fun __handleSseRequest(
|
|
1829
1849
|
onData(event.data)
|
1830
1850
|
} catch (e: CancellationException) {
|
1831
1851
|
onClose()
|
1852
|
+
httpResponse.cancel()
|
1832
1853
|
return@execute
|
1833
1854
|
}
|
1834
1855
|
}
|
@@ -1838,22 +1859,11 @@ private suspend fun __handleSseRequest(
|
|
1838
1859
|
return@execute
|
1839
1860
|
}
|
1840
1861
|
|
1841
|
-
"error" -> {
|
1842
|
-
val error = ${clientName}Error.fromJson(event.data)
|
1843
|
-
try {
|
1844
|
-
onError(error)
|
1845
|
-
} catch (e: CancellationException) {
|
1846
|
-
onClose()
|
1847
|
-
return@execute
|
1848
|
-
}
|
1849
|
-
}
|
1850
|
-
|
1851
1862
|
else -> {}
|
1852
1863
|
}
|
1853
1864
|
}
|
1854
1865
|
}
|
1855
|
-
__handleSseRequest(
|
1856
|
-
scope = scope,
|
1866
|
+
return@execute __handleSseRequest(
|
1857
1867
|
httpClient = httpClient,
|
1858
1868
|
url = url,
|
1859
1869
|
method = method,
|
@@ -1865,22 +1875,13 @@ private suspend fun __handleSseRequest(
|
|
1865
1875
|
bufferCapacity = bufferCapacity,
|
1866
1876
|
onOpen = onOpen,
|
1867
1877
|
onClose = onClose,
|
1868
|
-
onError = onError,
|
1869
1878
|
onData = onData,
|
1870
|
-
|
1879
|
+
onResponseError = onResponseError,
|
1871
1880
|
)
|
1872
1881
|
}
|
1873
1882
|
} catch (e: java.net.ConnectException) {
|
1874
|
-
|
1875
|
-
|
1876
|
-
code = 503,
|
1877
|
-
errorMessage = if (e.message != null) e.message!! else "Error connecting to $url",
|
1878
|
-
data = JsonPrimitive(e.toString()),
|
1879
|
-
stack = e.stackTraceToString().split("\\n"),
|
1880
|
-
)
|
1881
|
-
)
|
1882
|
-
__handleSseRequest(
|
1883
|
-
scope = scope,
|
1883
|
+
onRequestError(e)
|
1884
|
+
return __handleSseRequest(
|
1884
1885
|
httpClient = httpClient,
|
1885
1886
|
url = url,
|
1886
1887
|
method = method,
|
@@ -1892,14 +1893,12 @@ private suspend fun __handleSseRequest(
|
|
1892
1893
|
bufferCapacity = bufferCapacity,
|
1893
1894
|
onOpen = onOpen,
|
1894
1895
|
onClose = onClose,
|
1895
|
-
onError = onError,
|
1896
1896
|
onData = onData,
|
1897
|
-
|
1897
|
+
onResponseError = onResponseError,
|
1898
1898
|
)
|
1899
|
-
return
|
1900
1899
|
} catch (e: Exception) {
|
1901
|
-
|
1902
|
-
|
1900
|
+
onRequestError(e)
|
1901
|
+
return __handleSseRequest(
|
1903
1902
|
httpClient = httpClient,
|
1904
1903
|
url = url,
|
1905
1904
|
method = method,
|
@@ -1911,9 +1910,8 @@ private suspend fun __handleSseRequest(
|
|
1911
1910
|
bufferCapacity = bufferCapacity,
|
1912
1911
|
onOpen = onOpen,
|
1913
1912
|
onClose = onClose,
|
1914
|
-
onError = onError,
|
1915
1913
|
onData = onData,
|
1916
|
-
|
1914
|
+
onResponseError = onResponseError,
|
1917
1915
|
)
|
1918
1916
|
}
|
1919
1917
|
}`;
|
@@ -1926,14 +1924,14 @@ function getHeader(options) {
|
|
1926
1924
|
)
|
1927
1925
|
|
1928
1926
|
import io.ktor.client.*
|
1927
|
+
import io.ktor.client.call.*
|
1929
1928
|
import io.ktor.client.plugins.*
|
1930
1929
|
import io.ktor.client.request.*
|
1931
1930
|
import io.ktor.client.statement.*
|
1932
1931
|
import io.ktor.http.*
|
1933
1932
|
import io.ktor.utils.io.*
|
1934
|
-
import kotlinx.coroutines.
|
1935
|
-
import kotlinx.coroutines.
|
1936
|
-
import kotlinx.coroutines.launch
|
1933
|
+
import kotlinx.coroutines.cancel
|
1934
|
+
import kotlinx.coroutines.currentCoroutineContext
|
1937
1935
|
import kotlinx.coroutines.withContext
|
1938
1936
|
import kotlinx.serialization.encodeToString
|
1939
1937
|
import kotlinx.serialization.json.*
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@arrirpc/codegen-kotlin",
|
3
|
-
"version": "0.
|
3
|
+
"version": "0.61.0",
|
4
4
|
"type": "module",
|
5
5
|
"license": "MIT",
|
6
6
|
"author": {
|
@@ -22,6 +22,6 @@
|
|
22
22
|
"dist"
|
23
23
|
],
|
24
24
|
"dependencies": {
|
25
|
-
"@arrirpc/codegen-utils": "0.
|
25
|
+
"@arrirpc/codegen-utils": "0.61.0"
|
26
26
|
}
|
27
27
|
}
|