@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
@@ -31,7 +31,7 @@ export interface SDKModuleConfig {
31
31
  *
32
32
  * @default 'stable'
33
33
  */
34
- stability?: 'stable' | 'experimental' | 'internal';
34
+ stability?: "stable" | "experimental" | "internal";
35
35
  }
36
36
  /** Symbol used to store SDKModuleConfig on a decorated class. */
37
37
  export declare const SDK_MODULE_CONFIG: unique symbol;
@@ -89,7 +89,7 @@ export interface SDKRouteConfig {
89
89
  /** Override the generated method name for this route. */
90
90
  methodName?: string;
91
91
  /** Request body encoding. Defaults to `'json'`. */
92
- transport?: 'json' | 'multipart' | 'binary' | 'stream';
92
+ transport?: "json" | "multipart" | "binary" | "stream";
93
93
  /** Completely exclude this route from the generated SDK. */
94
94
  exclude?: boolean;
95
95
  /**
@@ -124,5 +124,25 @@ export interface SDKRouteConfig {
124
124
  * wrapper. e.g. `"SignalStreamEvent"` emits `AsyncIterable<SignalStreamEvent>`.
125
125
  */
126
126
  sseReturnType?: string;
127
+ /**
128
+ * Override the generated return type for this route.
129
+ *
130
+ * Useful for paginated list endpoints where the response body is a wrapper
131
+ * object (e.g. `{ data: T[], page: PageMeta }`) but the SDK consumer only
132
+ * cares about the inner array type.
133
+ *
134
+ * @example
135
+ * ```ts
136
+ * sdk: {
137
+ * methodName: 'listProjects',
138
+ * returnType: 'SignalProjectSchema[]',
139
+ * }
140
+ * ```
141
+ *
142
+ * The value is emitted verbatim as the `Promise<T>` type parameter.
143
+ * Type names are automatically collected for imports when they match
144
+ * known schema names.
145
+ */
146
+ returnType?: string;
127
147
  }
128
148
  //# sourceMappingURL=sdk-module.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sdk-module.d.ts","sourceRoot":"","sources":["../../src/types/sdk-module.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,QAAQ,GAAG,cAAc,GAAG,UAAU,CAAC;CACpD;AAED,iEAAiE;AACjE,eAAO,MAAM,iBAAiB,eAAsC,CAAC;AAErE;;;;GAIG;AACH,eAAO,MAAM,eAAe,8BAAqC,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,eAAe,IACvC,CAAC,SAAS,QAAQ,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EAC5D,QAAQ,CAAC,EACT,UAAU,qBAAqB,CAAC,CAAC,CAAC,KACjC,IAAI,CAUR;AAGD;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,cAAc;IAC7B,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAEvD,4DAA4D;IAC5D,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAE9B,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,eAAe,CAAC,EAAE,KAAK,CAAC;QACtB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IAEH;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB"}
1
+ {"version":3,"file":"sdk-module.d.ts","sourceRoot":"","sources":["../../src/types/sdk-module.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,WAAW,eAAe;IAC9B;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;;OAGG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAElB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;;;;;;;OAQG;IACH,SAAS,CAAC,EAAE,QAAQ,GAAG,cAAc,GAAG,UAAU,CAAC;CACpD;AAED,iEAAiE;AACjE,eAAO,MAAM,iBAAiB,eAAsC,CAAC;AAErE;;;;GAIG;AACH,eAAO,MAAM,eAAe,8BAAqC,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,eAAe,IACvC,CAAC,SAAS,QAAQ,MAAM,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,EAC5D,QAAQ,CAAC,EACT,UAAU,qBAAqB,CAAC,CAAC,CAAC,KACjC,IAAI,CAUR;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,cAAc;IAC7B,yDAAyD;IACzD,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,mDAAmD;IACnD,SAAS,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAEvD,4DAA4D;IAC5D,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,GAAG,MAAM,CAAC;IAE9B,wEAAwE;IACxE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,gEAAgE;IAChE,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,yDAAyD;IACzD,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;;OAGG;IACH,eAAe,CAAC,EAAE,KAAK,CAAC;QACtB,IAAI,EAAE,MAAM,CAAC;QACb,SAAS,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;KACtB,CAAC,CAAC;IAEH;;;;OAIG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;IAEvB;;;;;;;;;;;;;;;;;;OAkBG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}
@@ -1,5 +1,5 @@
1
1
  /** Symbol used to store SDKModuleConfig on a decorated class. */
2
- export const SDK_MODULE_CONFIG = Symbol('tesseract:sdkModuleConfig');
2
+ export const SDK_MODULE_CONFIG = Symbol("tesseract:sdkModuleConfig");
3
3
  /**
4
4
  * Module-level domain registry. Populated by `@SDKModule` and `sdkDomain()`.
5
5
  * Read by the Fastify plugin at generation time.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@apollo-deploy/tesseract",
3
- "version": "0.9.1",
3
+ "version": "1.2.0",
4
4
  "type": "module",
5
5
  "description": "Manifest-first SDK generator — turns sdk-manifold/v1 manifests into production-ready TypeScript SDKs",
6
6
  "bin": {
@@ -0,0 +1,95 @@
1
+ namespace {{namespace}};
2
+
3
+ using System;
4
+ using System.Collections.Generic;
5
+ using {{namespace}}.Api;
6
+
7
+ /// <summary>
8
+ /// Configuration for the {{clientName}} API client.
9
+ /// </summary>
10
+ public class {{clientName}}ClientConfig
11
+ {
12
+ /// <summary>
13
+ /// Base URL for all API requests.
14
+ /// </summary>
15
+ public string BaseUrl { get; set; } = "{{baseUrl}}";
16
+ {{#each securitySchemes}}
17
+ {{#if (eq type "apiKey")}}
18
+ /// <summary>
19
+ /// API key for the {{name}} security scheme.
20
+ /// </summary>
21
+ public string? {{pascalCase configKey}} { get; set; }
22
+ {{/if}}
23
+ {{#if (and (eq type "http") (eq scheme "bearer"))}}
24
+ /// <summary>
25
+ /// Bearer token for the {{name}} security scheme.
26
+ /// </summary>
27
+ public string? {{pascalCase configKey}} { get; set; }
28
+ {{/if}}
29
+ {{#if (eq type "oauth2")}}
30
+ /// <summary>
31
+ /// OAuth2 access token for the {{name}} security scheme.
32
+ /// </summary>
33
+ public string? {{pascalCase configKey}} { get; set; }
34
+ {{/if}}
35
+ {{#if (eq type "openIdConnect")}}
36
+ /// <summary>
37
+ /// OpenID Connect token for the {{name}} security scheme.
38
+ /// </summary>
39
+ public string? {{pascalCase configKey}} { get; set; }
40
+ {{/if}}
41
+ {{/each}}
42
+ /// <summary>
43
+ /// Request timeout in milliseconds.
44
+ /// </summary>
45
+ public int TimeoutMs { get; set; } = 15000;
46
+
47
+ /// <summary>
48
+ /// Maximum number of retry attempts for transient failures.
49
+ /// </summary>
50
+ public int MaxRetries { get; set; } = 3;
51
+
52
+ /// <summary>
53
+ /// Default headers sent with every request.
54
+ /// </summary>
55
+ public Dictionary<string, string>? DefaultHeaders { get; set; }
56
+ }
57
+
58
+ /// <summary>
59
+ /// Primary API client for {{title}}.
60
+ /// </summary>
61
+ public class {{clientName}}Client
62
+ {
63
+ private readonly Transport _transport;
64
+
65
+ {{#each groups}}
66
+ /// <summary>
67
+ /// {{#if description}}{{description}}{{else}}{{name}} operations{{/if}}
68
+ /// </summary>
69
+ public {{interfaceName}} {{pascalCase name}} { get; }
70
+ {{/each}}
71
+
72
+ /// <summary>
73
+ /// Creates a new {{clientName}} API client.
74
+ /// </summary>
75
+ /// <param name="config">Client configuration. If null, defaults are used.</param>
76
+ public {{clientName}}Client({{clientName}}ClientConfig? config = null)
77
+ {
78
+ config ??= new {{clientName}}ClientConfig();
79
+
80
+ _transport = new Transport(new TransportConfig
81
+ {
82
+ BaseUrl = config.BaseUrl,
83
+ {{#each securitySchemes}}
84
+ {{pascalCase configKey}} = config.{{pascalCase configKey}},
85
+ {{/each}}
86
+ TimeoutMs = config.TimeoutMs,
87
+ MaxRetries = config.MaxRetries,
88
+ DefaultHeaders = config.DefaultHeaders,
89
+ });
90
+
91
+ {{#each groups}}
92
+ {{pascalCase name}} = new {{interfaceName}}(_transport);
93
+ {{/each}}
94
+ }
95
+ }
@@ -0,0 +1,18 @@
1
+ <Project Sdk="Microsoft.NET.Sdk">
2
+
3
+ <PropertyGroup>
4
+ <TargetFramework>net8.0</TargetFramework>
5
+ <PackageId>{{packageName}}</PackageId>
6
+ <Version>{{packageVersion}}</Version>
7
+ <Description>{{#if description}}{{description}}{{else}}C# SDK for {{title}}{{/if}}</Description>
8
+ <Nullable>enable</Nullable>
9
+ <ImplicitUsings>enable</ImplicitUsings>
10
+ <RootNamespace>{{namespace}}</RootNamespace>
11
+ <GenerateDocumentationFile>true</GenerateDocumentationFile>
12
+ </PropertyGroup>
13
+
14
+ <ItemGroup>
15
+ <PackageReference Include="System.Text.Json" Version="8.0.*" />
16
+ </ItemGroup>
17
+
18
+ </Project>
@@ -0,0 +1,183 @@
1
+ namespace {{namespace}}.Api;
2
+
3
+ using System;
4
+ using System.Collections.Generic;
5
+ using System.IO;
6
+ using System.Net.Http;
7
+ using System.Text;
8
+ using System.Text.Json;
9
+ using System.Threading;
10
+ using System.Threading.Tasks;
11
+
12
+ /// <summary>
13
+ /// Provides access to {{name}} API operations.
14
+ /// </summary>
15
+ public class {{interfaceName}}
16
+ {
17
+ private readonly Transport _transport;
18
+
19
+ /// <summary>
20
+ /// Creates a new {{interfaceName}} instance.
21
+ /// </summary>
22
+ public {{interfaceName}}(Transport transport)
23
+ {
24
+ _transport = transport;
25
+ }
26
+
27
+ {{#each operations}}
28
+ {{#if isEventStream}}
29
+ /// <summary>
30
+ {{#if summary}}
31
+ /// {{summary}}
32
+ {{/if}}
33
+ {{#if description}}
34
+ /// {{description}}
35
+ {{/if}}
36
+ {{#if deprecated}}
37
+ /// [Obsolete] {{#if deprecationMessage}}{{deprecationMessage}}{{/if}}
38
+ {{/if}}
39
+ /// </summary>
40
+ {{#if deprecated}}
41
+ [Obsolete({{#if deprecationMessage}}"{{deprecationMessage}}"{{/if}})]
42
+ {{/if}}
43
+ public async IAsyncEnumerable<string> {{pascalCase name}}Async(
44
+ {{#each pathParams}}
45
+ {{type}}{{#if (not required)}}?{{/if}} {{name}},
46
+ {{/each}}
47
+ {{#if requestBody}}
48
+ {{requestBody.type}}{{#if (not requestBody.required)}}?{{/if}} body,
49
+ {{/if}}
50
+ {{#if queryType}}
51
+ {{queryType}}? query = null,
52
+ {{/if}}
53
+ CancellationToken cancellationToken = default)
54
+ {
55
+ var path = $"{{path}}"
56
+ {{#each pathParams}}
57
+ .Replace("{{{originalName}}}", Uri.EscapeDataString({{name}}?.ToString() ?? ""))
58
+ {{/each}}
59
+ ;
60
+
61
+ var queryParams = new Dictionary<string, string>();
62
+ {{#if queryType}}
63
+ if (query != null)
64
+ {
65
+ var json = JsonSerializer.Serialize(query);
66
+ var dict = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(json);
67
+ if (dict != null)
68
+ {
69
+ foreach (var (key, value) in dict)
70
+ {
71
+ if (value.ValueKind != JsonValueKind.Null)
72
+ queryParams[key] = value.ToString();
73
+ }
74
+ }
75
+ }
76
+ {{/if}}
77
+ {{#if (hasQueryParams this)}}
78
+ {{#each queryParams}}
79
+ if ({{name}} != null)
80
+ queryParams["{{originalName}}"] = {{name}}.ToString();
81
+ {{/each}}
82
+ {{/if}}
83
+
84
+ var response = await _transport.StreamAsync(
85
+ new Transport.Request
86
+ {
87
+ Method = HttpMethod.{{httpMethod}},
88
+ Path = path,
89
+ Query = queryParams.Count > 0 ? queryParams : null,
90
+ {{#if requestBody}}
91
+ Body = body,
92
+ ContentType = "{{requestBody.contentType}}",
93
+ {{/if}}
94
+ },
95
+ cancellationToken);
96
+
97
+ using var stream = await response.Content.ReadAsStreamAsync(cancellationToken);
98
+ using var reader = new StreamReader(stream);
99
+
100
+ while (!reader.EndOfStream)
101
+ {
102
+ cancellationToken.ThrowIfCancellationRequested();
103
+ var line = await reader.ReadLineAsync(cancellationToken);
104
+ if (line == null) break;
105
+
106
+ // Forward raw SSE lines
107
+ yield return line;
108
+ }
109
+ }
110
+
111
+ {{else}}
112
+ /// <summary>
113
+ {{#if summary}}
114
+ /// {{summary}}
115
+ {{/if}}
116
+ {{#if description}}
117
+ /// {{description}}
118
+ {{/if}}
119
+ {{#if deprecated}}
120
+ /// [Obsolete] {{#if deprecationMessage}}{{deprecationMessage}}{{/if}}
121
+ {{/if}}
122
+ /// </summary>
123
+ {{#if deprecated}}
124
+ [Obsolete({{#if deprecationMessage}}"{{deprecationMessage}}"{{/if}})]
125
+ {{/if}}
126
+ public async Task<{{#if responseType}}{{responseType}}{{else}}object{{/if}}> {{pascalCase name}}Async(
127
+ {{#each pathParams}}
128
+ {{type}}{{#if (not required)}}?{{/if}} {{name}},
129
+ {{/each}}
130
+ {{#if requestBody}}
131
+ {{requestBody.type}}{{#if (not requestBody.required)}}?{{/if}} body,
132
+ {{/if}}
133
+ {{#if queryType}}
134
+ {{queryType}}? query = null,
135
+ {{/if}}
136
+ CancellationToken cancellationToken = default)
137
+ {
138
+ var path = $"{{path}}"
139
+ {{#each pathParams}}
140
+ .Replace("{{{originalName}}}", Uri.EscapeDataString({{name}}?.ToString() ?? ""))
141
+ {{/each}}
142
+ ;
143
+
144
+ var queryParams = new Dictionary<string, string>();
145
+ {{#if queryType}}
146
+ if (query != null)
147
+ {
148
+ var json = JsonSerializer.Serialize(query);
149
+ var dict = JsonSerializer.Deserialize<Dictionary<string, JsonElement>>(json);
150
+ if (dict != null)
151
+ {
152
+ foreach (var (key, value) in dict)
153
+ {
154
+ if (value.ValueKind != JsonValueKind.Null)
155
+ queryParams[key] = value.ToString();
156
+ }
157
+ }
158
+ }
159
+ {{/if}}
160
+ {{#if (hasQueryParams this)}}
161
+ {{#each queryParams}}
162
+ if ({{name}} != null)
163
+ queryParams["{{originalName}}"] = {{name}}.ToString();
164
+ {{/each}}
165
+ {{/if}}
166
+
167
+ return await _transport.ExecuteAsync<{{#if responseType}}{{responseType}}{{else}}object{{/if}}>(
168
+ new Transport.Request
169
+ {
170
+ Method = HttpMethod.{{httpMethod}},
171
+ Path = path,
172
+ Query = queryParams.Count > 0 ? queryParams : null,
173
+ {{#if requestBody}}
174
+ Body = body,
175
+ ContentType = "{{requestBody.contentType}}",
176
+ {{/if}}
177
+ },
178
+ cancellationToken);
179
+ }
180
+
181
+ {{/if}}
182
+ {{/each}}
183
+ }
@@ -0,0 +1,45 @@
1
+ namespace {{namespace}};
2
+
3
+ using System;
4
+
5
+ /// <summary>
6
+ /// Represents an error returned by the API.
7
+ /// </summary>
8
+ public class SdkException : Exception
9
+ {
10
+ /// <summary>
11
+ /// HTTP status code.
12
+ /// </summary>
13
+ public int Status { get; }
14
+
15
+ /// <summary>
16
+ /// Machine-readable error code from the API.
17
+ /// </summary>
18
+ public string? Code { get; }
19
+
20
+ /// <summary>
21
+ /// Unique request identifier for support.
22
+ /// </summary>
23
+ public string? RequestId { get; }
24
+
25
+ /// <summary>
26
+ /// Creates a new SdkException.
27
+ /// </summary>
28
+ public SdkException(int status, string? code, string message, string? requestId, Exception? innerException = null)
29
+ : base(message, innerException)
30
+ {
31
+ Status = status;
32
+ Code = code;
33
+ RequestId = requestId;
34
+ }
35
+
36
+ /// <summary>
37
+ /// Returns a string representation of the error.
38
+ /// </summary>
39
+ public override string ToString()
40
+ {
41
+ if (!string.IsNullOrEmpty(Code))
42
+ return $"[{Status}] {Code}: {Message}";
43
+ return $"[{Status}] {Message}";
44
+ }
45
+ }
@@ -0,0 +1,76 @@
1
+ # {{title}} .NET SDK
2
+
3
+ [![NuGet](https://img.shields.io/nuget/v/{{packageName}}.svg)](https://www.nuget.org/packages/{{packageName}}/)
4
+
5
+ The official .NET SDK for {{#if description}}{{description}}{{else}}the {{title}} API{{/if}}.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ dotnet add package {{packageName}}
11
+ ```
12
+
13
+ ## Quick Start
14
+
15
+ ```csharp
16
+ using {{namespace}};
17
+
18
+ {{#each securitySchemes}}
19
+ {{#if (eq type "apiKey")}}
20
+ var config = new {{../clientName}}ClientConfig
21
+ {
22
+ {{pascalCase configKey}} = "your-api-key"{{#if (and (eq type "apiKey") (eq in "header"))}}{{/if}}
23
+ };
24
+ {{/if}}
25
+ {{#if (and (eq type "http") (eq scheme "bearer"))}}
26
+ var config = new {{../clientName}}ClientConfig
27
+ {
28
+ {{pascalCase configKey}} = "your-bearer-token"
29
+ };
30
+ {{/if}}
31
+ {{/each}}
32
+ {{#unless securitySchemes.length}}
33
+ var config = new {{clientName}}ClientConfig();
34
+ {{/unless}}
35
+
36
+ var client = new {{clientName}}Client(config);
37
+
38
+ {{#each groups}}
39
+ {{#with operations.[0]}}
40
+ // {{../interfaceName}}.{{pascalCase name}} example
41
+ var result = await client.{{pascalCase ../name}}.{{pascalCase name}}Async({{#each ../pathParams}}"{{this}}"{{#unless @last}}, {{/unless}}{{/each}}{{#if requestBody}}{{#if ../pathParams.length}}, {{/if}}new {{requestBody.type}}(){}{{/if}});
42
+ Console.WriteLine(result);
43
+ {{/with}}
44
+ {{/each}}
45
+ ```
46
+
47
+ ## API Reference
48
+
49
+ | Domain | Description |
50
+ |--------|-------------|
51
+ {{#each groups}}
52
+ | `{{interfaceName}}` | {{#if description}}{{description}}{{else}}{{name}} operations{{/if}} |
53
+ {{/each}}
54
+
55
+ ## Error Handling
56
+
57
+ All async methods throw `SdkException` on API errors. Use try-catch to handle errors:
58
+
59
+ ```csharp
60
+ try
61
+ {
62
+ var result = await client.{{#each groups}}{{#if @first}}{{pascalCase name}}{{/if}}{{/each}}.{{#each groups}}{{#if @first}}{{#with operations.[0]}}{{pascalCase name}}Async(){{/with}}{{/if}}{{/each}};
63
+ }
64
+ catch (SdkException ex)
65
+ {
66
+ Console.WriteLine($"Status: {ex.Status}, Code: {ex.Code}, RequestId: {ex.RequestId}");
67
+ }
68
+ ```
69
+
70
+ ## Requirements
71
+
72
+ - .NET 8.0 or later
73
+
74
+ ## License
75
+
76
+ {{#if license}}{{license}}{{else}}MIT{{/if}}