@arrirpc/codegen-kotlin 0.60.3 → 0.61.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/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
|
}
|