@apollo-deploy/tesseract 0.9.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (114) hide show
  1. package/dist/adapters/csharp/index.d.ts +12 -0
  2. package/dist/adapters/csharp/index.d.ts.map +1 -0
  3. package/dist/adapters/csharp/index.js +99 -0
  4. package/dist/adapters/csharp/index.js.map +1 -0
  5. package/dist/adapters/go/index.d.ts +12 -0
  6. package/dist/adapters/go/index.d.ts.map +1 -0
  7. package/dist/adapters/go/index.js +135 -0
  8. package/dist/adapters/go/index.js.map +1 -0
  9. package/dist/adapters/kotlin/index.d.ts +13 -0
  10. package/dist/adapters/kotlin/index.d.ts.map +1 -0
  11. package/dist/adapters/kotlin/index.js +188 -0
  12. package/dist/adapters/kotlin/index.js.map +1 -0
  13. package/dist/adapters/php/index.d.ts +20 -0
  14. package/dist/adapters/php/index.d.ts.map +1 -0
  15. package/dist/adapters/php/index.js +123 -0
  16. package/dist/adapters/php/index.js.map +1 -0
  17. package/dist/adapters/python/index.d.ts +12 -0
  18. package/dist/adapters/python/index.d.ts.map +1 -0
  19. package/dist/adapters/python/index.js +145 -0
  20. package/dist/adapters/python/index.js.map +1 -0
  21. package/dist/adapters/ruby/index.d.ts +12 -0
  22. package/dist/adapters/ruby/index.d.ts.map +1 -0
  23. package/dist/adapters/ruby/index.js +86 -0
  24. package/dist/adapters/ruby/index.js.map +1 -0
  25. package/dist/adapters/rust/index.d.ts +13 -0
  26. package/dist/adapters/rust/index.d.ts.map +1 -0
  27. package/dist/adapters/rust/index.js +213 -0
  28. package/dist/adapters/rust/index.js.map +1 -0
  29. package/dist/adapters/typescript/emitter/emitSchema.d.ts +1 -1
  30. package/dist/adapters/typescript/emitter/emitSchema.d.ts.map +1 -1
  31. package/dist/adapters/typescript/emitter/emitSchema.js +1 -1
  32. package/dist/adapters/typescript/emitter/emitSchema.js.map +1 -1
  33. package/dist/adapters/typescript/emitter/emitTypeScriptModels.d.ts +2 -2
  34. package/dist/adapters/typescript/emitter/emitTypeScriptModels.d.ts.map +1 -1
  35. package/dist/adapters/typescript/emitter/emitTypeScriptModels.js +5 -3
  36. package/dist/adapters/typescript/emitter/emitTypeScriptModels.js.map +1 -1
  37. package/dist/adapters/typescript/emitter/importCollector.d.ts +1 -1
  38. package/dist/adapters/typescript/emitter/importCollector.d.ts.map +1 -1
  39. package/dist/adapters/typescript/index.d.ts.map +1 -1
  40. package/dist/adapters/typescript/index.js +43 -2
  41. package/dist/adapters/typescript/index.js.map +1 -1
  42. package/dist/cli.js +2 -1
  43. package/dist/cli.js.map +1 -1
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +14 -0
  46. package/dist/index.js.map +1 -1
  47. package/dist/pipeline/intake.d.ts.map +1 -1
  48. package/dist/pipeline/intake.js +32 -21
  49. package/dist/pipeline/intake.js.map +1 -1
  50. package/dist/types/ir.d.ts +1 -1
  51. package/dist/types/ir.d.ts.map +1 -1
  52. package/dist/types/sdk-module.d.ts +22 -2
  53. package/dist/types/sdk-module.d.ts.map +1 -1
  54. package/dist/types/sdk-module.js +1 -1
  55. package/package.json +1 -1
  56. package/templates/csharp/client.hbs +95 -0
  57. package/templates/csharp/csproj.hbs +18 -0
  58. package/templates/csharp/domain.hbs +183 -0
  59. package/templates/csharp/errors.hbs +45 -0
  60. package/templates/csharp/readme.hbs +76 -0
  61. package/templates/csharp/transport.hbs +291 -0
  62. package/templates/csharp/types.hbs +104 -0
  63. package/templates/go/client.hbs +158 -0
  64. package/templates/go/domain.hbs +89 -0
  65. package/templates/go/errors.hbs +38 -0
  66. package/templates/go/go-mod.hbs +6 -0
  67. package/templates/go/readme.hbs +73 -0
  68. package/templates/go/transport.hbs +379 -0
  69. package/templates/go/types.hbs +80 -0
  70. package/templates/go/utils.hbs +45 -0
  71. package/templates/kotlin/build-gradle.hbs +151 -0
  72. package/templates/kotlin/client.hbs +57 -0
  73. package/templates/kotlin/domain.hbs +73 -0
  74. package/templates/kotlin/errors.hbs +42 -0
  75. package/templates/kotlin/gradle-properties.hbs +2 -0
  76. package/templates/kotlin/readme.hbs +133 -0
  77. package/templates/kotlin/settings-gradle.hbs +1 -0
  78. package/templates/kotlin/transport.hbs +246 -0
  79. package/templates/kotlin/types.hbs +100 -0
  80. package/templates/php/client.hbs +74 -0
  81. package/templates/php/composer.hbs +19 -0
  82. package/templates/php/domain.hbs +173 -0
  83. package/templates/php/errors.hbs +131 -0
  84. package/templates/php/readme.hbs +89 -0
  85. package/templates/php/transport.hbs +285 -0
  86. package/templates/php/types.hbs +95 -0
  87. package/templates/python/client.hbs +102 -0
  88. package/templates/python/domain.hbs +139 -0
  89. package/templates/python/index.hbs +20 -0
  90. package/templates/python/pyproject.hbs +26 -0
  91. package/templates/python/readme.hbs +64 -0
  92. package/templates/python/resources-init.hbs +11 -0
  93. package/templates/python/transport.hbs +191 -0
  94. package/templates/python/types-errors.hbs +75 -0
  95. package/templates/python/types.hbs +79 -0
  96. package/templates/ruby/Gemfile.hbs +5 -0
  97. package/templates/ruby/client.hbs +86 -0
  98. package/templates/ruby/domain.hbs +110 -0
  99. package/templates/ruby/errors.hbs +150 -0
  100. package/templates/ruby/gemspec.hbs +30 -0
  101. package/templates/ruby/index.hbs +54 -0
  102. package/templates/ruby/readme.hbs +113 -0
  103. package/templates/ruby/transport.hbs +177 -0
  104. package/templates/ruby/types.hbs +126 -0
  105. package/templates/ruby/version.hbs +5 -0
  106. package/templates/rust/api-mod.hbs +3 -0
  107. package/templates/rust/cargo.hbs +22 -0
  108. package/templates/rust/client.hbs +114 -0
  109. package/templates/rust/domain.hbs +94 -0
  110. package/templates/rust/error.hbs +74 -0
  111. package/templates/rust/lib.hbs +85 -0
  112. package/templates/rust/readme.hbs +77 -0
  113. package/templates/rust/transport.hbs +287 -0
  114. package/templates/rust/types.hbs +142 -0
@@ -0,0 +1,151 @@
1
+ plugins {
2
+ kotlin("jvm") version "1.9.25"
3
+ kotlin("plugin.serialization") version "1.9.25"
4
+ `java-library`
5
+ `maven-publish`
6
+ signing
7
+ }
8
+
9
+ group = {{json groupId}}
10
+ version = {{#if packageVersion}}{{json packageVersion}}{{else}}"0.1.0"{{/if}}
11
+
12
+ repositories {
13
+ mavenCentral()
14
+ }
15
+
16
+ dependencies {
17
+ api(kotlin("stdlib"))
18
+ api("org.jetbrains.kotlinx:kotlinx-serialization-json:1.7.3")
19
+ api("io.ktor:ktor-client-core:2.3.12")
20
+
21
+ implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.8.1")
22
+ implementation("io.ktor:ktor-client-cio:2.3.12")
23
+ implementation("io.ktor:ktor-client-content-negotiation:2.3.12")
24
+ implementation("io.ktor:ktor-serialization-kotlinx-json:2.3.12")
25
+
26
+ testImplementation(kotlin("test"))
27
+ testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1")
28
+ }
29
+
30
+ kotlin {
31
+ jvmToolchain(17)
32
+ }
33
+
34
+ tasks.test {
35
+ useJUnitPlatform()
36
+ }
37
+
38
+ java {
39
+ withSourcesJar()
40
+ withJavadocJar()
41
+ }
42
+
43
+ publishing {
44
+ publications {
45
+ create<MavenPublication>("maven") {
46
+ groupId = project.group.toString()
47
+ artifactId = {{json artifactId}}
48
+ version = project.version.toString()
49
+
50
+ from(components["java"])
51
+
52
+ pom {
53
+ name.set({{json title}})
54
+ description.set({{json pomDescription}})
55
+
56
+ providers.gradleProperty("pomUrl")
57
+ .orElse(providers.environmentVariable("POM_URL"))
58
+ .orNull
59
+ ?.let { url.set(it) }
60
+
61
+ licenses {
62
+ license {
63
+ name.set("MIT")
64
+ url.set("https://opensource.org/licenses/MIT")
65
+ }
66
+ }
67
+
68
+ val pomDeveloperId = providers.gradleProperty("pomDeveloperId")
69
+ .orElse(providers.environmentVariable("POM_DEVELOPER_ID"))
70
+ .orNull
71
+ val pomDeveloperName = providers.gradleProperty("pomDeveloperName")
72
+ .orElse(providers.environmentVariable("POM_DEVELOPER_NAME"))
73
+ .orNull
74
+
75
+ if (pomDeveloperId != null || pomDeveloperName != null) {
76
+ developers {
77
+ developer {
78
+ pomDeveloperId?.let { id.set(it) }
79
+ pomDeveloperName?.let { name.set(it) }
80
+ }
81
+ }
82
+ }
83
+
84
+ val pomScmUrl = providers.gradleProperty("pomScmUrl")
85
+ .orElse(providers.environmentVariable("POM_SCM_URL"))
86
+ .orNull
87
+ val pomScmConnection = providers.gradleProperty("pomScmConnection")
88
+ .orElse(providers.environmentVariable("POM_SCM_CONNECTION"))
89
+ .orNull
90
+ val pomScmDeveloperConnection = providers.gradleProperty("pomScmDeveloperConnection")
91
+ .orElse(providers.environmentVariable("POM_SCM_DEVELOPER_CONNECTION"))
92
+ .orNull
93
+
94
+ if (pomScmUrl != null || pomScmConnection != null || pomScmDeveloperConnection != null) {
95
+ scm {
96
+ pomScmUrl?.let { url.set(it) }
97
+ pomScmConnection?.let { connection.set(it) }
98
+ pomScmDeveloperConnection?.let { developerConnection.set(it) }
99
+ }
100
+ }
101
+ }
102
+ }
103
+ }
104
+
105
+ repositories {
106
+ maven {
107
+ name = providers.gradleProperty("mavenRepositoryName")
108
+ .orElse(providers.environmentVariable("MAVEN_REPOSITORY_NAME"))
109
+ .orElse("generated")
110
+ .get()
111
+
112
+ url = uri(
113
+ providers.gradleProperty("mavenRepositoryUrl")
114
+ .orElse(providers.environmentVariable("MAVEN_REPOSITORY_URL"))
115
+ .orElse(layout.buildDirectory.dir("maven-repository").map { it.asFile.toURI().toString() })
116
+ .get()
117
+ )
118
+
119
+ val publishUsername = providers.gradleProperty("mavenRepositoryUsername")
120
+ .orElse(providers.environmentVariable("MAVEN_REPOSITORY_USERNAME"))
121
+ .orNull
122
+ val publishPassword = providers.gradleProperty("mavenRepositoryPassword")
123
+ .orElse(providers.environmentVariable("MAVEN_REPOSITORY_PASSWORD"))
124
+ .orNull
125
+
126
+ if (publishUsername != null || publishPassword != null) {
127
+ credentials {
128
+ username = publishUsername
129
+ password = publishPassword
130
+ }
131
+ }
132
+ }
133
+ }
134
+ }
135
+
136
+ val signingKey = providers.gradleProperty("signingInMemoryKey")
137
+ .orElse(providers.environmentVariable("SIGNING_IN_MEMORY_KEY"))
138
+ .orNull
139
+ ?.replace("\\n", "\n")
140
+ val signingPassword = providers.gradleProperty("signingInMemoryKeyPassword")
141
+ .orElse(providers.environmentVariable("SIGNING_IN_MEMORY_KEY_PASSWORD"))
142
+ .orNull
143
+
144
+ signing {
145
+ isRequired = signingKey != null
146
+
147
+ if (signingKey != null) {
148
+ useInMemoryPgpKeys(signingKey, signingPassword)
149
+ sign(publishing.publications["maven"])
150
+ }
151
+ }
@@ -0,0 +1,57 @@
1
+ package {{packageName}}
2
+
3
+ import kotlinx.coroutines.*
4
+
5
+ /**
6
+ * Configuration for the {{title}} API client.
7
+ */
8
+ data class ClientConfig(
9
+ val baseUrl: String = "{{baseUrl}}",
10
+ {{#each securitySchemes}}
11
+ {{#if (eq type "apiKey")}}
12
+ /** API key for the `{{name}}` security scheme. */
13
+ val {{configKey}}: String? = null,
14
+ {{/if}}
15
+ {{#if (and (eq type "http") (eq scheme "bearer"))}}
16
+ /** Bearer token for the `{{name}}` security scheme. */
17
+ val {{configKey}}: String? = null,
18
+ {{/if}}
19
+ {{#if (eq type "oauth2")}}
20
+ /** OAuth2 access token for the `{{name}}` security scheme. */
21
+ val {{configKey}}: String? = null,
22
+ {{/if}}
23
+ {{#if (eq type "openIdConnect")}}
24
+ /** OpenID Connect access token for the `{{name}}` security scheme. */
25
+ val {{configKey}}: String? = null,
26
+ {{/if}}
27
+ {{/each}}
28
+ /** Request timeout in milliseconds. */
29
+ val timeoutMs: Long = 15000,
30
+ /** Maximum number of retry attempts. */
31
+ val maxRetries: Int = 3,
32
+ )
33
+
34
+ /**
35
+ * Primary API client for {{title}}.
36
+ *
37
+ * Provides access to all domain-specific API groups.
38
+ */
39
+ class {{clientName}}Client(
40
+ config: ClientConfig = ClientConfig()
41
+ ) {
42
+ private val transport: Transport = Transport(
43
+ TransportConfig(
44
+ baseUrl = config.baseUrl,
45
+ {{#each securitySchemes}}
46
+ {{configKey}} = config.{{configKey}},
47
+ {{/each}}
48
+ timeoutMs = config.timeoutMs,
49
+ maxRetries = config.maxRetries,
50
+ )
51
+ )
52
+
53
+ {{#each groups}}
54
+ /** {{#if description}}{{description}}{{else}}{{interfaceName}} operations.{{/if}} */
55
+ val {{name}}: {{interfaceName}} = {{interfaceName}}(transport)
56
+ {{/each}}
57
+ }
@@ -0,0 +1,73 @@
1
+ package {{packageName}}
2
+
3
+ import io.ktor.http.*
4
+ import kotlinx.coroutines.*
5
+
6
+ /**
7
+ * {{#if description}}{{description}}{{else}}{{interfaceName}} API operations.{{/if}}
8
+ */
9
+ class {{interfaceName}}(
10
+ private val transport: Transport
11
+ ) {
12
+ {{#each operations}}
13
+ {{#if summary}}
14
+ /**
15
+ * {{summary}}{{#if description}}
16
+ *
17
+ * {{description}}{{/if}}
18
+ */
19
+ {{/if}}
20
+ {{#if deprecated}}
21
+ @Deprecated(
22
+ message = "{{#if deprecationMessage}}{{deprecationMessage}}{{else}}This operation is deprecated.{{/if}}",
23
+ )
24
+ {{/if}}
25
+ suspend fun {{name}}(
26
+ {{#each pathParams}}
27
+ {{name}}: {{{kotlinType type}}},
28
+ {{/each}}
29
+ {{#if requestBody}}
30
+ body: {{{requestBody.kotlinType}}},
31
+ {{/if}}
32
+ {{#if queryType}}
33
+ query: {{{kotlinType queryType}}}? = null,
34
+ {{/if}}
35
+ ): {{{kotlinResponseType}}} {
36
+ val path = "{{path}}"{{#each pathParams}}.replace("{" + "{{name}}" + "}", {{name}}.toString()){{/each}}
37
+
38
+ {{#if (hasQueryParams this)}}
39
+ val queryMap = mutableMapOf<String, String?>()
40
+ {{#each _queryParams}}
41
+ queryMap["{{originalName}}"] = null // TODO: extract from typed query if available
42
+ {{/each}}
43
+ {{else if queryType}}
44
+ val queryMap: Map<String, String?>? = null // TODO: serialize query type
45
+ {{else}}
46
+ val queryMap: Map<String, String?>? = null
47
+ {{/if}}
48
+
49
+ {{#if (or (hasRequestBody this) (needsRequestHeaders this))}}
50
+ val headers = mutableMapOf<String, String>()
51
+ {{#if (hasRequestBody this)}}
52
+ {{#if (and (neq requestBody.contentType "application/json") (neq requestBody.contentType "multipart/form-data"))}}
53
+ headers["Content-Type"] = "{{requestBody.contentType}}"
54
+ {{/if}}
55
+ {{/if}}
56
+ {{#each headerParams}}
57
+ // TODO: inject header param '{{originalName}}' from header options
58
+ {{/each}}
59
+ {{else}}
60
+ val headers: Map<String, String>? = null
61
+ {{/if}}
62
+
63
+ return transport.execute<{{{kotlinResponseType}}}>(
64
+ method = HttpMethod.{{httpMethod}},
65
+ path = path,
66
+ query = queryMap,
67
+ body = {{#if requestBody}}body{{else}}null{{/if}},
68
+ headers = headers{{#unless (or (hasRequestBody this) (needsRequestHeaders this))}}{{/unless}},
69
+ )
70
+ }
71
+
72
+ {{/each}}
73
+ }
@@ -0,0 +1,42 @@
1
+ package {{packageName}}
2
+
3
+ /**
4
+ * Primary exception type for the {{packageName}} SDK.
5
+ *
6
+ * All API methods throw [SdkException] on failure.
7
+ */
8
+ class SdkException(
9
+ /** HTTP status code, if this is an API error. */
10
+ val status: Int?,
11
+ /** Machine-readable error code (if available). */
12
+ val code: String?,
13
+ /** Human-readable error message. */
14
+ override val message: String,
15
+ /** Server-assigned request ID for support. */
16
+ val requestId: String?,
17
+ /** The underlying cause, if any. */
18
+ cause: Throwable? = null,
19
+ ) : Exception(message, cause) {
20
+
21
+ /** Returns `true` if this error was caused by the server (5xx). */
22
+ fun isServerError(): Boolean = status != null && status in 500..599
23
+
24
+ /** Returns `true` if this error was caused by the client (4xx). */
25
+ fun isClientError(): Boolean = status != null && status in 400..499
26
+
27
+ /** Returns `true` if this is a network error (should be retried safely). */
28
+ fun isNetworkError(): Boolean = status == null
29
+
30
+ /** Returns `true` if this error is retryable. */
31
+ fun isRetryable(): Boolean = isNetworkError() || status in setOf(429, 502, 503, 504)
32
+
33
+ override fun toString(): String {
34
+ val sb = StringBuilder("SdkException(")
35
+ if (status != null) sb.append("status=$status, ")
36
+ if (code != null) sb.append("code='$code', ")
37
+ sb.append("message='$message'")
38
+ if (requestId != null) sb.append(", requestId='$requestId'")
39
+ sb.append(")")
40
+ return sb.toString()
41
+ }
42
+ }
@@ -0,0 +1,2 @@
1
+ kotlin.code.style=official
2
+ org.gradle.jvmargs=-Xmx1g
@@ -0,0 +1,133 @@
1
+ # {{title}}
2
+
3
+ {{#if description}}{{description}}{{/if}}
4
+
5
+ {{#unless description}}An auto-generated Kotlin SDK for the {{title}} API.{{/unless}}
6
+
7
+ ## Installation
8
+
9
+ ### Gradle
10
+
11
+ Add the dependency to your `build.gradle.kts`:
12
+
13
+ ```kotlin
14
+ repositories {
15
+ mavenCentral()
16
+ // If publishing to a private repository, add it here.
17
+ }
18
+
19
+ dependencies {
20
+ implementation("{{groupId}}:{{artifactId}}:{{#if packageVersion}}{{packageVersion}}{{else}}0.1.0{{/if}}")
21
+ }
22
+ ```
23
+
24
+ ### Maven
25
+
26
+ ```xml
27
+ <dependency>
28
+ <groupId>{{groupId}}</groupId>
29
+ <artifactId>{{artifactId}}</artifactId>
30
+ <version>{{#if packageVersion}}{{packageVersion}}{{else}}0.1.0{{/if}}</version>
31
+ </dependency>
32
+ ```
33
+
34
+ ## Publishing
35
+
36
+ Publish to your local Maven cache:
37
+
38
+ ```bash
39
+ gradle publishToMavenLocal
40
+ ```
41
+
42
+ Publish to a Maven repository:
43
+
44
+ ```bash
45
+ MAVEN_REPOSITORY_URL="https://maven.example.com/releases" \
46
+ MAVEN_REPOSITORY_USERNAME="username" \
47
+ MAVEN_REPOSITORY_PASSWORD="password" \
48
+ gradle publish
49
+ ```
50
+
51
+ The generated Gradle project also supports equivalent Gradle properties:
52
+
53
+ - `mavenRepositoryUrl`
54
+ - `mavenRepositoryUsername`
55
+ - `mavenRepositoryPassword`
56
+ - `mavenRepositoryName`
57
+
58
+ For signed publications, provide `SIGNING_IN_MEMORY_KEY` and `SIGNING_IN_MEMORY_KEY_PASSWORD` or the matching Gradle properties `signingInMemoryKey` and `signingInMemoryKeyPassword`.
59
+
60
+ For repositories that require richer POM metadata, set `POM_URL`, `POM_SCM_URL`, `POM_SCM_CONNECTION`, `POM_SCM_DEVELOPER_CONNECTION`, `POM_DEVELOPER_ID`, and `POM_DEVELOPER_NAME` or the equivalent lower-camel Gradle properties.
61
+
62
+ ## Quick Start
63
+
64
+ ```kotlin
65
+ import {{packageName}}.Client
66
+ import {{packageName}}.ClientConfig
67
+ import kotlinx.coroutines.runBlocking
68
+
69
+ fun main() = runBlocking {
70
+ val config = ClientConfig(
71
+ {{#each securitySchemes}}
72
+ {{#if (eq type "apiKey")}}
73
+ {{configKey}} = "your-api-key",
74
+ {{/if}}
75
+ {{#if (and (eq type "http") (eq scheme "bearer"))}}
76
+ {{configKey}} = "your-bearer-token",
77
+ {{/if}}
78
+ {{/each}}
79
+ )
80
+
81
+ val client = Client(config)
82
+
83
+ {{#each groups}}
84
+ {{#if @first}}
85
+ // val result = client.{{name}}.someOperation()
86
+ {{/if}}
87
+ {{/each}}
88
+ }
89
+ ```
90
+
91
+ ## API Reference
92
+
93
+ {{#each groups}}
94
+ ### {{interfaceName}}
95
+
96
+ {{#if description}}
97
+ {{description}}
98
+ {{/if}}
99
+
100
+ | Method | HTTP | Description |
101
+ |--------|------|-------------|
102
+ {{#each operations}}
103
+ | `{{name}}()` | `{{httpMethod}}` | {{#if summary}}{{summary}}{{else}}—{{/if}} |
104
+ {{/each}}
105
+
106
+ {{/each}}
107
+
108
+ ## Error Handling
109
+
110
+ All API methods throw `SdkException` on failure. The exception contains:
111
+
112
+ - `status`: HTTP status code (for API errors)
113
+ - `code`: Machine-readable error code (if available)
114
+ - `message`: Human-readable error message
115
+ - `requestId`: Server-assigned request ID for support
116
+
117
+ ```kotlin
118
+ try {
119
+ val result = client.users.getUser("user-123")
120
+ println("Success: $result")
121
+ } catch (e: SdkException) {
122
+ when {
123
+ e.isClientError() -> println("Bad request: ${e.message}")
124
+ e.isServerError() -> println("Server error (${e.status}): ${e.message}")
125
+ e.isNetworkError() -> println("Network error: ${e.message}")
126
+ else -> println("Error: ${e.message}")
127
+ }
128
+ }
129
+ ```
130
+
131
+ ## License
132
+
133
+ MIT
@@ -0,0 +1 @@
1
+ rootProject.name = "{{artifactId}}"