@alagoni97/cli 0.72.1

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 (244) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +336 -0
  3. package/bin/dev.cmd +3 -0
  4. package/bin/dev.mjs +3 -0
  5. package/bin/run.cmd +3 -0
  6. package/bin/run.mjs +4 -0
  7. package/dist/LoggingInterface.d.ts +123 -0
  8. package/dist/LoggingInterface.js +300 -0
  9. package/dist/PersistedConfig.d.ts +46 -0
  10. package/dist/PersistedConfig.js +94 -0
  11. package/dist/browser/adapters/output.d.ts +69 -0
  12. package/dist/browser/adapters/output.js +91 -0
  13. package/dist/browser/config.d.ts +18 -0
  14. package/dist/browser/config.js +59 -0
  15. package/dist/browser/generate.d.ts +20 -0
  16. package/dist/browser/generate.js +129 -0
  17. package/dist/browser/index.d.ts +17 -0
  18. package/dist/browser/index.js +26 -0
  19. package/dist/browser/parser.d.ts +9 -0
  20. package/dist/browser/parser.js +61 -0
  21. package/dist/browser/shims/asyncapi-parser.d.ts +30 -0
  22. package/dist/browser/shims/asyncapi-parser.js +52 -0
  23. package/dist/browser/shims/fs.d.ts +190 -0
  24. package/dist/browser/shims/fs.js +188 -0
  25. package/dist/browser/shims/json-schema-ref-parser.d.ts +73 -0
  26. package/dist/browser/shims/json-schema-ref-parser.js +246 -0
  27. package/dist/browser/shims/swagger-parser.d.ts +20 -0
  28. package/dist/browser/shims/swagger-parser.js +40 -0
  29. package/dist/codegen/configurationSchemaBuilder.d.ts +15 -0
  30. package/dist/codegen/configurationSchemaBuilder.js +48 -0
  31. package/dist/codegen/configurations.d.ts +29 -0
  32. package/dist/codegen/configurations.js +260 -0
  33. package/dist/codegen/detection.d.ts +19 -0
  34. package/dist/codegen/detection.js +174 -0
  35. package/dist/codegen/errors.d.ts +111 -0
  36. package/dist/codegen/errors.js +352 -0
  37. package/dist/codegen/generators/generic/custom.d.ts +75 -0
  38. package/dist/codegen/generators/generic/custom.js +66 -0
  39. package/dist/codegen/generators/index.d.ts +14 -0
  40. package/dist/codegen/generators/index.js +42 -0
  41. package/dist/codegen/generators/typescript/channels/asyncapi.d.ts +10 -0
  42. package/dist/codegen/generators/typescript/channels/asyncapi.js +131 -0
  43. package/dist/codegen/generators/typescript/channels/index.d.ts +8 -0
  44. package/dist/codegen/generators/typescript/channels/index.js +142 -0
  45. package/dist/codegen/generators/typescript/channels/openapi.d.ts +9 -0
  46. package/dist/codegen/generators/typescript/channels/openapi.js +168 -0
  47. package/dist/codegen/generators/typescript/channels/protocols/amqp/index.d.ts +7 -0
  48. package/dist/codegen/generators/typescript/channels/protocols/amqp/index.js +149 -0
  49. package/dist/codegen/generators/typescript/channels/protocols/amqp/publishExchange.d.ts +5 -0
  50. package/dist/codegen/generators/typescript/channels/protocols/amqp/publishExchange.js +106 -0
  51. package/dist/codegen/generators/typescript/channels/protocols/amqp/publishQueue.d.ts +3 -0
  52. package/dist/codegen/generators/typescript/channels/protocols/amqp/publishQueue.js +102 -0
  53. package/dist/codegen/generators/typescript/channels/protocols/amqp/subscribeQueue.d.ts +3 -0
  54. package/dist/codegen/generators/typescript/channels/protocols/amqp/subscribeQueue.js +133 -0
  55. package/dist/codegen/generators/typescript/channels/protocols/eventsource/express.d.ts +3 -0
  56. package/dist/codegen/generators/typescript/channels/protocols/eventsource/express.js +100 -0
  57. package/dist/codegen/generators/typescript/channels/protocols/eventsource/fetch.d.ts +5 -0
  58. package/dist/codegen/generators/typescript/channels/protocols/eventsource/fetch.js +144 -0
  59. package/dist/codegen/generators/typescript/channels/protocols/eventsource/index.d.ts +6 -0
  60. package/dist/codegen/generators/typescript/channels/protocols/eventsource/index.js +132 -0
  61. package/dist/codegen/generators/typescript/channels/protocols/http/client.d.ts +10 -0
  62. package/dist/codegen/generators/typescript/channels/protocols/http/client.js +224 -0
  63. package/dist/codegen/generators/typescript/channels/protocols/http/common-types.d.ts +14 -0
  64. package/dist/codegen/generators/typescript/channels/protocols/http/common-types.js +800 -0
  65. package/dist/codegen/generators/typescript/channels/protocols/http/index.d.ts +8 -0
  66. package/dist/codegen/generators/typescript/channels/protocols/http/index.js +96 -0
  67. package/dist/codegen/generators/typescript/channels/protocols/http/security.d.ts +48 -0
  68. package/dist/codegen/generators/typescript/channels/protocols/http/security.js +491 -0
  69. package/dist/codegen/generators/typescript/channels/protocols/kafka/index.d.ts +6 -0
  70. package/dist/codegen/generators/typescript/channels/protocols/kafka/index.js +127 -0
  71. package/dist/codegen/generators/typescript/channels/protocols/kafka/publish.d.ts +3 -0
  72. package/dist/codegen/generators/typescript/channels/protocols/kafka/publish.js +108 -0
  73. package/dist/codegen/generators/typescript/channels/protocols/kafka/subscribe.d.ts +3 -0
  74. package/dist/codegen/generators/typescript/channels/protocols/kafka/subscribe.js +154 -0
  75. package/dist/codegen/generators/typescript/channels/protocols/kafka/utils.d.ts +11 -0
  76. package/dist/codegen/generators/typescript/channels/protocols/kafka/utils.js +58 -0
  77. package/dist/codegen/generators/typescript/channels/protocols/mqtt/index.d.ts +6 -0
  78. package/dist/codegen/generators/typescript/channels/protocols/mqtt/index.js +113 -0
  79. package/dist/codegen/generators/typescript/channels/protocols/mqtt/publish.d.ts +3 -0
  80. package/dist/codegen/generators/typescript/channels/protocols/mqtt/publish.js +99 -0
  81. package/dist/codegen/generators/typescript/channels/protocols/mqtt/subscribe.d.ts +3 -0
  82. package/dist/codegen/generators/typescript/channels/protocols/mqtt/subscribe.js +186 -0
  83. package/dist/codegen/generators/typescript/channels/protocols/nats/corePublish.d.ts +3 -0
  84. package/dist/codegen/generators/typescript/channels/protocols/nats/corePublish.js +90 -0
  85. package/dist/codegen/generators/typescript/channels/protocols/nats/coreReply.d.ts +3 -0
  86. package/dist/codegen/generators/typescript/channels/protocols/nats/coreReply.js +142 -0
  87. package/dist/codegen/generators/typescript/channels/protocols/nats/coreRequest.d.ts +3 -0
  88. package/dist/codegen/generators/typescript/channels/protocols/nats/coreRequest.js +100 -0
  89. package/dist/codegen/generators/typescript/channels/protocols/nats/coreSubscribe.d.ts +3 -0
  90. package/dist/codegen/generators/typescript/channels/protocols/nats/coreSubscribe.js +143 -0
  91. package/dist/codegen/generators/typescript/channels/protocols/nats/index.d.ts +11 -0
  92. package/dist/codegen/generators/typescript/channels/protocols/nats/index.js +224 -0
  93. package/dist/codegen/generators/typescript/channels/protocols/nats/jetstreamPublish.d.ts +3 -0
  94. package/dist/codegen/generators/typescript/channels/protocols/nats/jetstreamPublish.js +89 -0
  95. package/dist/codegen/generators/typescript/channels/protocols/nats/jetstreamPullSubscribe.d.ts +3 -0
  96. package/dist/codegen/generators/typescript/channels/protocols/nats/jetstreamPullSubscribe.js +146 -0
  97. package/dist/codegen/generators/typescript/channels/protocols/nats/jetstreamPushSubscription.d.ts +3 -0
  98. package/dist/codegen/generators/typescript/channels/protocols/nats/jetstreamPushSubscription.js +149 -0
  99. package/dist/codegen/generators/typescript/channels/protocols/nats/utils.d.ts +35 -0
  100. package/dist/codegen/generators/typescript/channels/protocols/nats/utils.js +120 -0
  101. package/dist/codegen/generators/typescript/channels/protocols/websocket/index.d.ts +7 -0
  102. package/dist/codegen/generators/typescript/channels/protocols/websocket/index.js +152 -0
  103. package/dist/codegen/generators/typescript/channels/protocols/websocket/publish.d.ts +3 -0
  104. package/dist/codegen/generators/typescript/channels/protocols/websocket/publish.js +64 -0
  105. package/dist/codegen/generators/typescript/channels/protocols/websocket/register.d.ts +3 -0
  106. package/dist/codegen/generators/typescript/channels/protocols/websocket/register.js +115 -0
  107. package/dist/codegen/generators/typescript/channels/protocols/websocket/subscribe.d.ts +3 -0
  108. package/dist/codegen/generators/typescript/channels/protocols/websocket/subscribe.js +151 -0
  109. package/dist/codegen/generators/typescript/channels/types.d.ts +181 -0
  110. package/dist/codegen/generators/typescript/channels/types.js +131 -0
  111. package/dist/codegen/generators/typescript/channels/utils.d.ts +64 -0
  112. package/dist/codegen/generators/typescript/channels/utils.js +163 -0
  113. package/dist/codegen/generators/typescript/client/index.d.ts +8 -0
  114. package/dist/codegen/generators/typescript/client/index.js +61 -0
  115. package/dist/codegen/generators/typescript/client/protocols/nats/corePublish.d.ts +6 -0
  116. package/dist/codegen/generators/typescript/client/protocols/nats/corePublish.js +53 -0
  117. package/dist/codegen/generators/typescript/client/protocols/nats/coreSubscribe.d.ts +6 -0
  118. package/dist/codegen/generators/typescript/client/protocols/nats/coreSubscribe.js +90 -0
  119. package/dist/codegen/generators/typescript/client/protocols/nats/jetStreamPullSubscription.d.ts +6 -0
  120. package/dist/codegen/generators/typescript/client/protocols/nats/jetStreamPullSubscription.js +83 -0
  121. package/dist/codegen/generators/typescript/client/protocols/nats/jetstreamPublish.d.ts +6 -0
  122. package/dist/codegen/generators/typescript/client/protocols/nats/jetstreamPublish.js +54 -0
  123. package/dist/codegen/generators/typescript/client/protocols/nats/jetstreamPushSubscription.d.ts +6 -0
  124. package/dist/codegen/generators/typescript/client/protocols/nats/jetstreamPushSubscription.js +82 -0
  125. package/dist/codegen/generators/typescript/client/protocols/nats.d.ts +2 -0
  126. package/dist/codegen/generators/typescript/client/protocols/nats.js +182 -0
  127. package/dist/codegen/generators/typescript/client/types.d.ts +49 -0
  128. package/dist/codegen/generators/typescript/client/types.js +37 -0
  129. package/dist/codegen/generators/typescript/headers.d.ts +54 -0
  130. package/dist/codegen/generators/typescript/headers.js +138 -0
  131. package/dist/codegen/generators/typescript/index.d.ts +7 -0
  132. package/dist/codegen/generators/typescript/index.js +38 -0
  133. package/dist/codegen/generators/typescript/models.d.ts +21761 -0
  134. package/dist/codegen/generators/typescript/models.js +64 -0
  135. package/dist/codegen/generators/typescript/parameters.d.ts +37 -0
  136. package/dist/codegen/generators/typescript/parameters.js +101 -0
  137. package/dist/codegen/generators/typescript/payloads.d.ts +73 -0
  138. package/dist/codegen/generators/typescript/payloads.js +250 -0
  139. package/dist/codegen/generators/typescript/types.d.ts +34 -0
  140. package/dist/codegen/generators/typescript/types.js +70 -0
  141. package/dist/codegen/generators/typescript/utils.d.ts +38 -0
  142. package/dist/codegen/generators/typescript/utils.js +195 -0
  143. package/dist/codegen/index.d.ts +7 -0
  144. package/dist/codegen/index.js +38 -0
  145. package/dist/codegen/inputs/asyncapi/generators/headers.d.ts +3 -0
  146. package/dist/codegen/inputs/asyncapi/generators/headers.js +41 -0
  147. package/dist/codegen/inputs/asyncapi/generators/parameters.d.ts +14 -0
  148. package/dist/codegen/inputs/asyncapi/generators/parameters.js +120 -0
  149. package/dist/codegen/inputs/asyncapi/generators/payloads.d.ts +16 -0
  150. package/dist/codegen/inputs/asyncapi/generators/payloads.js +124 -0
  151. package/dist/codegen/inputs/asyncapi/generators/types.d.ts +9 -0
  152. package/dist/codegen/inputs/asyncapi/generators/types.js +61 -0
  153. package/dist/codegen/inputs/asyncapi/index.d.ts +1 -0
  154. package/dist/codegen/inputs/asyncapi/index.js +7 -0
  155. package/dist/codegen/inputs/asyncapi/parser.d.ts +4 -0
  156. package/dist/codegen/inputs/asyncapi/parser.js +90 -0
  157. package/dist/codegen/inputs/index.d.ts +3 -0
  158. package/dist/codegen/inputs/index.js +19 -0
  159. package/dist/codegen/inputs/jsonschema/generators/index.d.ts +1 -0
  160. package/dist/codegen/inputs/jsonschema/generators/index.js +5 -0
  161. package/dist/codegen/inputs/jsonschema/generators/models.d.ts +7 -0
  162. package/dist/codegen/inputs/jsonschema/generators/models.js +26 -0
  163. package/dist/codegen/inputs/jsonschema/index.d.ts +1 -0
  164. package/dist/codegen/inputs/jsonschema/index.js +7 -0
  165. package/dist/codegen/inputs/jsonschema/parser.d.ts +31 -0
  166. package/dist/codegen/inputs/jsonschema/parser.js +128 -0
  167. package/dist/codegen/inputs/openapi/generators/headers.d.ts +3 -0
  168. package/dist/codegen/inputs/openapi/generators/headers.js +101 -0
  169. package/dist/codegen/inputs/openapi/generators/parameters.d.ts +10 -0
  170. package/dist/codegen/inputs/openapi/generators/parameters.js +852 -0
  171. package/dist/codegen/inputs/openapi/generators/payloads.d.ts +3 -0
  172. package/dist/codegen/inputs/openapi/generators/payloads.js +231 -0
  173. package/dist/codegen/inputs/openapi/generators/types.d.ts +9 -0
  174. package/dist/codegen/inputs/openapi/generators/types.js +86 -0
  175. package/dist/codegen/inputs/openapi/index.d.ts +2 -0
  176. package/dist/codegen/inputs/openapi/index.js +8 -0
  177. package/dist/codegen/inputs/openapi/parser.d.ts +4 -0
  178. package/dist/codegen/inputs/openapi/parser.js +115 -0
  179. package/dist/codegen/inputs/openapi/security.d.ts +56 -0
  180. package/dist/codegen/inputs/openapi/security.js +193 -0
  181. package/dist/codegen/modelina/index.d.ts +2 -0
  182. package/dist/codegen/modelina/index.js +20 -0
  183. package/dist/codegen/modelina/presets/index.d.ts +3 -0
  184. package/dist/codegen/modelina/presets/index.js +14 -0
  185. package/dist/codegen/modelina/presets/primitives.d.ts +34 -0
  186. package/dist/codegen/modelina/presets/primitives.js +211 -0
  187. package/dist/codegen/modelina/presets/union.d.ts +33 -0
  188. package/dist/codegen/modelina/presets/union.js +197 -0
  189. package/dist/codegen/modelina/presets/validation.d.ts +66 -0
  190. package/dist/codegen/modelina/presets/validation.js +183 -0
  191. package/dist/codegen/modelina/types.d.ts +61845 -0
  192. package/dist/codegen/modelina/types.js +412 -0
  193. package/dist/codegen/output/filesystem.d.ts +30 -0
  194. package/dist/codegen/output/filesystem.js +61 -0
  195. package/dist/codegen/output/index.d.ts +16 -0
  196. package/dist/codegen/output/index.js +57 -0
  197. package/dist/codegen/output/memory.d.ts +54 -0
  198. package/dist/codegen/output/memory.js +81 -0
  199. package/dist/codegen/output/modelina.d.ts +30 -0
  200. package/dist/codegen/output/modelina.js +30 -0
  201. package/dist/codegen/output/types.d.ts +47 -0
  202. package/dist/codegen/output/types.js +6 -0
  203. package/dist/codegen/renderer.d.ts +13 -0
  204. package/dist/codegen/renderer.js +309 -0
  205. package/dist/codegen/schemaPostProcess.d.ts +25 -0
  206. package/dist/codegen/schemaPostProcess.js +38 -0
  207. package/dist/codegen/types.d.ts +285187 -0
  208. package/dist/codegen/types.js +177 -0
  209. package/dist/codegen/utils.d.ts +126 -0
  210. package/dist/codegen/utils.js +373 -0
  211. package/dist/commands/base.d.ts +18 -0
  212. package/dist/commands/base.js +59 -0
  213. package/dist/commands/generate.d.ts +46 -0
  214. package/dist/commands/generate.js +305 -0
  215. package/dist/commands/init.d.ts +55 -0
  216. package/dist/commands/init.js +544 -0
  217. package/dist/commands/telemetry.d.ts +25 -0
  218. package/dist/commands/telemetry.js +115 -0
  219. package/dist/index.d.ts +29 -0
  220. package/dist/index.js +35 -0
  221. package/dist/telemetry/anonymize.d.ts +19 -0
  222. package/dist/telemetry/anonymize.js +73 -0
  223. package/dist/telemetry/collector.d.ts +26 -0
  224. package/dist/telemetry/collector.js +57 -0
  225. package/dist/telemetry/config.d.ts +32 -0
  226. package/dist/telemetry/config.js +97 -0
  227. package/dist/telemetry/events.d.ts +72 -0
  228. package/dist/telemetry/events.js +5 -0
  229. package/dist/telemetry/index.d.ts +46 -0
  230. package/dist/telemetry/index.js +91 -0
  231. package/dist/telemetry/notice.d.ts +8 -0
  232. package/dist/telemetry/notice.js +50 -0
  233. package/dist/telemetry/sender.d.ts +14 -0
  234. package/dist/telemetry/sender.js +125 -0
  235. package/dist/utils/gitignore.d.ts +66 -0
  236. package/dist/utils/gitignore.js +111 -0
  237. package/dist/utils/inputSource.d.ts +3 -0
  238. package/dist/utils/inputSource.js +26 -0
  239. package/dist/utils/refResolvers.d.ts +29 -0
  240. package/dist/utils/refResolvers.js +83 -0
  241. package/dist/utils/remoteFetch.d.ts +18 -0
  242. package/dist/utils/remoteFetch.js +64 -0
  243. package/oclif.manifest.json +510 -0
  244. package/package.json +155 -0
@@ -0,0 +1,800 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.renderHttpCommonTypes = void 0;
4
+ const security_1 = require("./security");
5
+ /**
6
+ * Generates common types and helper functions shared across all HTTP client functions.
7
+ * This should be called once per protocol generation to avoid code duplication.
8
+ *
9
+ * @param securitySchemes - Optional security schemes extracted from OpenAPI.
10
+ * When provided, only relevant auth types are generated.
11
+ * When undefined/empty, all auth types are generated for backward compatibility.
12
+ */
13
+ function renderHttpCommonTypes(securitySchemes) {
14
+ const requirements = (0, security_1.analyzeSecuritySchemes)(securitySchemes);
15
+ const securityTypes = (0, security_1.renderSecurityTypes)(securitySchemes, requirements);
16
+ return `// ============================================================================
17
+ // Common Types - Shared across all HTTP client functions
18
+ // ============================================================================
19
+
20
+ /**
21
+ * Standard HTTP response interface that wraps fetch-like responses
22
+ */
23
+ export interface HttpResponse {
24
+ ok: boolean;
25
+ status: number;
26
+ statusText: string;
27
+ headers?: Headers | Record<string, string>;
28
+ json: () => Record<any, any> | Promise<Record<any, any>>;
29
+ }
30
+
31
+ /**
32
+ * Pagination info extracted from response
33
+ */
34
+ export interface PaginationInfo {
35
+ /** Total number of items (if available from headers like X-Total-Count) */
36
+ totalCount?: number;
37
+ /** Total number of pages (if available) */
38
+ totalPages?: number;
39
+ /** Current page/offset */
40
+ currentOffset?: number;
41
+ /** Items per page */
42
+ limit?: number;
43
+ /** Next cursor (for cursor-based pagination) */
44
+ nextCursor?: string;
45
+ /** Previous cursor */
46
+ prevCursor?: string;
47
+ /** Whether there are more items */
48
+ hasMore?: boolean;
49
+ }
50
+
51
+ /**
52
+ * Rich response wrapper returned by HTTP client functions
53
+ */
54
+ export interface HttpClientResponse<T> {
55
+ /** The deserialized response payload */
56
+ data: T;
57
+ /** HTTP status code */
58
+ status: number;
59
+ /** HTTP status text */
60
+ statusText: string;
61
+ /** Response headers */
62
+ headers: Record<string, string>;
63
+ /** Raw JSON response before deserialization */
64
+ rawData: Record<string, any>;
65
+ /** Pagination info extracted from response (if applicable) */
66
+ pagination?: PaginationInfo;
67
+ /** Fetch the next page (if pagination is configured and more data exists) */
68
+ getNextPage?: () => Promise<HttpClientResponse<T>>;
69
+ /** Fetch the previous page (if pagination is configured) */
70
+ getPrevPage?: () => Promise<HttpClientResponse<T>>;
71
+ /** Check if there's a next page */
72
+ hasNextPage?: () => boolean;
73
+ /** Check if there's a previous page */
74
+ hasPrevPage?: () => boolean;
75
+ }
76
+
77
+ /**
78
+ * HTTP request parameters passed to the request hook
79
+ */
80
+ export interface HttpRequestParams {
81
+ url: string;
82
+ headers?: Record<string, string | string[]>;
83
+ method: 'GET' | 'POST' | 'PUT' | 'PATCH' | 'DELETE' | 'OPTIONS' | 'HEAD';
84
+ credentials?: RequestCredentials;
85
+ body?: any;
86
+ }
87
+
88
+ /**
89
+ * Token response structure for OAuth2 flows
90
+ */
91
+ export interface TokenResponse {
92
+ accessToken: string;
93
+ refreshToken?: string;
94
+ expiresIn?: number;
95
+ }
96
+
97
+ ${securityTypes}
98
+
99
+ /**
100
+ * Feature flags indicating which auth types are available.
101
+ * Used internally to conditionally call auth-specific helpers.
102
+ */
103
+ const AUTH_FEATURES = {
104
+ oauth2: ${requirements.oauth2}
105
+ } as const;
106
+
107
+ /**
108
+ * Default values for API key authentication derived from the spec.
109
+ * These match the defaults documented in the ApiKeyAuth interface.
110
+ */
111
+ const API_KEY_DEFAULTS = {
112
+ name: '${(0, security_1.escapeStringForCodeGen)((0, security_1.getApiKeyDefaults)(requirements.apiKeySchemes).name)}',
113
+ in: '${(0, security_1.escapeStringForCodeGen)((0, security_1.getApiKeyDefaults)(requirements.apiKeySchemes).in)}' as 'header' | 'query' | 'cookie'
114
+ } as const;
115
+
116
+ // ============================================================================
117
+ // Pagination Types
118
+ // ============================================================================
119
+
120
+ /**
121
+ * Where to place pagination parameters
122
+ */
123
+ export type PaginationLocation = 'query' | 'header';
124
+
125
+ /**
126
+ * Offset-based pagination configuration
127
+ */
128
+ export interface OffsetPagination {
129
+ type: 'offset';
130
+ in?: PaginationLocation; // Where to place params (default: 'query')
131
+ offset: number;
132
+ limit: number;
133
+ offsetParam?: string; // Param name for offset (default: 'offset' for query, 'X-Offset' for header)
134
+ limitParam?: string; // Param name for limit (default: 'limit' for query, 'X-Limit' for header)
135
+ }
136
+
137
+ /**
138
+ * Cursor-based pagination configuration
139
+ */
140
+ export interface CursorPagination {
141
+ type: 'cursor';
142
+ in?: PaginationLocation; // Where to place params (default: 'query')
143
+ cursor?: string;
144
+ limit?: number;
145
+ cursorParam?: string; // Param name for cursor (default: 'cursor' for query, 'X-Cursor' for header)
146
+ limitParam?: string; // Param name for limit (default: 'limit' for query, 'X-Limit' for header)
147
+ }
148
+
149
+ /**
150
+ * Page-based pagination configuration
151
+ */
152
+ export interface PagePagination {
153
+ type: 'page';
154
+ in?: PaginationLocation; // Where to place params (default: 'query')
155
+ page: number;
156
+ pageSize: number;
157
+ pageParam?: string; // Param name for page (default: 'page' for query, 'X-Page' for header)
158
+ pageSizeParam?: string; // Param name for page size (default: 'pageSize' for query, 'X-Page-Size' for header)
159
+ }
160
+
161
+ /**
162
+ * Range-based pagination (typically used with headers)
163
+ * Follows RFC 7233 style: Range: items=0-24
164
+ */
165
+ export interface RangePagination {
166
+ type: 'range';
167
+ in?: 'header'; // Range pagination is typically header-only
168
+ start: number;
169
+ end: number;
170
+ unit?: string; // Range unit (default: 'items')
171
+ rangeHeader?: string; // Header name (default: 'Range')
172
+ }
173
+
174
+ /**
175
+ * Union type for all pagination methods
176
+ */
177
+ export type PaginationConfig = OffsetPagination | CursorPagination | PagePagination | RangePagination;
178
+
179
+ // ============================================================================
180
+ // Retry Configuration
181
+ // ============================================================================
182
+
183
+ /**
184
+ * Retry policy configuration for failed requests
185
+ */
186
+ export interface RetryConfig {
187
+ maxRetries?: number; // Maximum number of retry attempts (default: 3)
188
+ initialDelayMs?: number; // Initial delay before first retry (default: 1000)
189
+ maxDelayMs?: number; // Maximum delay between retries (default: 30000)
190
+ backoffMultiplier?: number; // Multiplier for exponential backoff (default: 2)
191
+ retryableStatusCodes?: number[]; // Status codes to retry (default: [408, 429, 500, 502, 503, 504])
192
+ retryOnNetworkError?: boolean; // Retry on network errors (default: true)
193
+ onRetry?: (attempt: number, delay: number, error: Error) => void; // Callback on each retry
194
+ }
195
+
196
+ // ============================================================================
197
+ // Hooks Configuration - Extensible callback system
198
+ // ============================================================================
199
+
200
+ /**
201
+ * Hooks for customizing HTTP client behavior
202
+ */
203
+ export interface HttpHooks {
204
+ /**
205
+ * Called before each request to transform/modify the request parameters
206
+ * Return modified params or undefined to use original
207
+ */
208
+ beforeRequest?: (params: HttpRequestParams) => HttpRequestParams | Promise<HttpRequestParams>;
209
+
210
+ /**
211
+ * The actual request implementation - allows swapping fetch for axios, etc.
212
+ * Default: uses node-fetch
213
+ */
214
+ makeRequest?: (params: HttpRequestParams) => Promise<HttpResponse>;
215
+
216
+ /**
217
+ * Called after each response for logging, metrics, etc.
218
+ * Can transform the response before it's processed
219
+ */
220
+ afterResponse?: (response: HttpResponse, params: HttpRequestParams) => HttpResponse | Promise<HttpResponse>;
221
+
222
+ /**
223
+ * Called on request error for logging, error transformation, etc.
224
+ */
225
+ onError?: (error: Error, params: HttpRequestParams) => Error | Promise<Error>;
226
+ }
227
+
228
+ // ============================================================================
229
+ // Common Request Context
230
+ // ============================================================================
231
+
232
+ /**
233
+ * Base context shared by all HTTP client functions
234
+ */
235
+ export interface HttpClientContext {
236
+ server?: string;
237
+ path?: string;
238
+
239
+ // Authentication - grouped for better autocomplete
240
+ auth?: AuthConfig;
241
+
242
+ // Pagination configuration
243
+ pagination?: PaginationConfig;
244
+
245
+ // Retry configuration
246
+ retry?: RetryConfig;
247
+
248
+ // Hooks for extensibility
249
+ hooks?: HttpHooks;
250
+
251
+ // Additional options
252
+ additionalHeaders?: Record<string, string | string[]>;
253
+
254
+ // Query parameters
255
+ queryParams?: Record<string, string | number | boolean | undefined>;
256
+ }
257
+
258
+ // ============================================================================
259
+ // Helper Functions - Shared logic extracted for reuse
260
+ // ============================================================================
261
+
262
+ /**
263
+ * Default retry configuration
264
+ */
265
+ const DEFAULT_RETRY_CONFIG: Required<RetryConfig> = {
266
+ maxRetries: 3,
267
+ initialDelayMs: 1000,
268
+ maxDelayMs: 30000,
269
+ backoffMultiplier: 2,
270
+ retryableStatusCodes: [408, 429, 500, 502, 503, 504],
271
+ retryOnNetworkError: true,
272
+ onRetry: () => {},
273
+ };
274
+
275
+ /**
276
+ * Default request hook implementation using node-fetch
277
+ */
278
+ const defaultMakeRequest = async (params: HttpRequestParams): Promise<HttpResponse> => {
279
+ return NodeFetch.default(params.url, {
280
+ body: params.body,
281
+ method: params.method,
282
+ headers: params.headers
283
+ }) as unknown as HttpResponse;
284
+ };
285
+
286
+ /**
287
+ * Apply authentication to headers and URL based on auth config
288
+ */
289
+ function applyAuth(
290
+ auth: AuthConfig | undefined,
291
+ headers: Record<string, string | string[]>,
292
+ url: string
293
+ ): { headers: Record<string, string | string[]>; url: string } {
294
+ if (!auth) return { headers, url };
295
+
296
+ switch (auth.type) {
297
+ case 'bearer':
298
+ headers['Authorization'] = \`Bearer \${auth.token}\`;
299
+ break;
300
+
301
+ case 'basic': {
302
+ const credentials = Buffer.from(\`\${auth.username}:\${auth.password}\`).toString('base64');
303
+ headers['Authorization'] = \`Basic \${credentials}\`;
304
+ break;
305
+ }
306
+
307
+ case 'apiKey': {
308
+ const keyName = auth.name ?? API_KEY_DEFAULTS.name;
309
+ const keyIn = auth.in ?? API_KEY_DEFAULTS.in;
310
+
311
+ if (keyIn === 'header') {
312
+ headers[keyName] = auth.key;
313
+ } else if (keyIn === 'query') {
314
+ const separator = url.includes('?') ? '&' : '?';
315
+ url = \`\${url}\${separator}\${keyName}=\${encodeURIComponent(auth.key)}\`;
316
+ } else if (keyIn === 'cookie') {
317
+ headers['Cookie'] = \`\${keyName}=\${auth.key}\`;
318
+ }
319
+ break;
320
+ }
321
+
322
+ case 'oauth2': {
323
+ // If we have an access token, use it directly
324
+ // Token flows (client_credentials, password) are handled separately
325
+ if (auth.accessToken) {
326
+ headers['Authorization'] = \`Bearer \${auth.accessToken}\`;
327
+ }
328
+ break;
329
+ }
330
+ }
331
+
332
+ return { headers, url };
333
+ }
334
+
335
+ /**
336
+ * Apply pagination parameters to URL and/or headers based on configuration
337
+ */
338
+ function applyPagination(
339
+ pagination: PaginationConfig | undefined,
340
+ url: string,
341
+ headers: Record<string, string | string[]>
342
+ ): { url: string; headers: Record<string, string | string[]> } {
343
+ if (!pagination) return { url, headers };
344
+
345
+ const location = pagination.in ?? 'query';
346
+ const isHeader = location === 'header';
347
+
348
+ // Helper to get default param names based on location
349
+ const getDefaultName = (queryName: string, headerName: string) =>
350
+ isHeader ? headerName : queryName;
351
+
352
+ const queryParams = new URLSearchParams();
353
+ const headerParams: Record<string, string> = {};
354
+
355
+ const addParam = (name: string, value: string) => {
356
+ if (isHeader) {
357
+ headerParams[name] = value;
358
+ } else {
359
+ queryParams.append(name, value);
360
+ }
361
+ };
362
+
363
+ switch (pagination.type) {
364
+ case 'offset':
365
+ addParam(
366
+ pagination.offsetParam ?? getDefaultName('offset', 'X-Offset'),
367
+ String(pagination.offset)
368
+ );
369
+ addParam(
370
+ pagination.limitParam ?? getDefaultName('limit', 'X-Limit'),
371
+ String(pagination.limit)
372
+ );
373
+ break;
374
+
375
+ case 'cursor':
376
+ if (pagination.cursor) {
377
+ addParam(
378
+ pagination.cursorParam ?? getDefaultName('cursor', 'X-Cursor'),
379
+ pagination.cursor
380
+ );
381
+ }
382
+ if (pagination.limit !== undefined) {
383
+ addParam(
384
+ pagination.limitParam ?? getDefaultName('limit', 'X-Limit'),
385
+ String(pagination.limit)
386
+ );
387
+ }
388
+ break;
389
+
390
+ case 'page':
391
+ addParam(
392
+ pagination.pageParam ?? getDefaultName('page', 'X-Page'),
393
+ String(pagination.page)
394
+ );
395
+ addParam(
396
+ pagination.pageSizeParam ?? getDefaultName('pageSize', 'X-Page-Size'),
397
+ String(pagination.pageSize)
398
+ );
399
+ break;
400
+
401
+ case 'range': {
402
+ // Range pagination is always header-based (RFC 7233 style)
403
+ const unit = pagination.unit ?? 'items';
404
+ const headerName = pagination.rangeHeader ?? 'Range';
405
+ headerParams[headerName] = \`\${unit}=\${pagination.start}-\${pagination.end}\`;
406
+ break;
407
+ }
408
+ }
409
+
410
+ // Apply query params to URL
411
+ const queryString = queryParams.toString();
412
+ if (queryString) {
413
+ const separator = url.includes('?') ? '&' : '?';
414
+ url = \`\${url}\${separator}\${queryString}\`;
415
+ }
416
+
417
+ // Merge header params
418
+ const updatedHeaders = { ...headers, ...headerParams };
419
+
420
+ return { url, headers: updatedHeaders };
421
+ }
422
+
423
+ /**
424
+ * Apply query parameters to URL
425
+ */
426
+ function applyQueryParams(queryParams: Record<string, string | number | boolean | undefined> | undefined, url: string): string {
427
+ if (!queryParams) return url;
428
+
429
+ const params = new URLSearchParams();
430
+ for (const [key, value] of Object.entries(queryParams)) {
431
+ if (value !== undefined) {
432
+ params.append(key, String(value));
433
+ }
434
+ }
435
+
436
+ const paramString = params.toString();
437
+ if (!paramString) return url;
438
+
439
+ const separator = url.includes('?') ? '&' : '?';
440
+ return \`\${url}\${separator}\${paramString}\`;
441
+ }
442
+
443
+ /**
444
+ * Sleep for a specified number of milliseconds
445
+ */
446
+ function sleep(ms: number): Promise<void> {
447
+ return new Promise(resolve => setTimeout(resolve, ms));
448
+ }
449
+
450
+ /**
451
+ * Calculate delay for exponential backoff
452
+ */
453
+ function calculateBackoffDelay(
454
+ attempt: number,
455
+ config: Required<RetryConfig>
456
+ ): number {
457
+ const delay = config.initialDelayMs * Math.pow(config.backoffMultiplier, attempt - 1);
458
+ return Math.min(delay, config.maxDelayMs);
459
+ }
460
+
461
+ /**
462
+ * Determine if a request should be retried based on error/response
463
+ */
464
+ function shouldRetry(
465
+ error: Error | null,
466
+ response: HttpResponse | null,
467
+ config: Required<RetryConfig>,
468
+ attempt: number
469
+ ): boolean {
470
+ if (attempt >= config.maxRetries) return false;
471
+
472
+ if (error && config.retryOnNetworkError) return true;
473
+
474
+ if (response && config.retryableStatusCodes.includes(response.status)) return true;
475
+
476
+ return false;
477
+ }
478
+
479
+ /**
480
+ * Execute request with retry logic
481
+ */
482
+ async function executeWithRetry(
483
+ params: HttpRequestParams,
484
+ makeRequest: (params: HttpRequestParams) => Promise<HttpResponse>,
485
+ retryConfig?: RetryConfig
486
+ ): Promise<HttpResponse> {
487
+ const config = { ...DEFAULT_RETRY_CONFIG, ...retryConfig };
488
+ let lastError: Error | null = null;
489
+ let lastResponse: HttpResponse | null = null;
490
+
491
+ for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
492
+ try {
493
+ if (attempt > 0) {
494
+ const delay = calculateBackoffDelay(attempt, config);
495
+ config.onRetry(attempt, delay, lastError ?? new Error('Retry attempt'));
496
+ await sleep(delay);
497
+ }
498
+
499
+ const response = await makeRequest(params);
500
+
501
+ // Check if we should retry this response
502
+ if (!shouldRetry(null, response, config, attempt + 1)) {
503
+ return response;
504
+ }
505
+
506
+ lastResponse = response;
507
+ lastError = new Error(\`HTTP Error: \${response.status} \${response.statusText}\`);
508
+ } catch (error) {
509
+ lastError = error instanceof Error ? error : new Error(String(error));
510
+
511
+ if (!shouldRetry(lastError, null, config, attempt + 1)) {
512
+ throw lastError;
513
+ }
514
+ }
515
+ }
516
+
517
+ // All retries exhausted
518
+ if (lastResponse) {
519
+ return lastResponse;
520
+ }
521
+ throw lastError ?? new Error('Request failed after retries');
522
+ }
523
+
524
+ /**
525
+ * Handle HTTP error status codes with standardized messages
526
+ */
527
+ function handleHttpError(status: number, statusText: string): never {
528
+ switch (status) {
529
+ case 401:
530
+ throw new Error('Unauthorized');
531
+ case 403:
532
+ throw new Error('Forbidden');
533
+ case 404:
534
+ throw new Error('Not Found');
535
+ case 500:
536
+ throw new Error('Internal Server Error');
537
+ default:
538
+ throw new Error(\`HTTP Error: \${status} \${statusText}\`);
539
+ }
540
+ }
541
+
542
+ /**
543
+ * Extract headers from response into a plain object
544
+ */
545
+ function extractHeaders(response: HttpResponse): Record<string, string> {
546
+ const headers: Record<string, string> = {};
547
+
548
+ if (response.headers) {
549
+ if (typeof (response.headers as any).forEach === 'function') {
550
+ // Headers object (fetch API)
551
+ (response.headers as Headers).forEach((value, key) => {
552
+ headers[key.toLowerCase()] = value;
553
+ });
554
+ } else {
555
+ // Plain object
556
+ for (const [key, value] of Object.entries(response.headers)) {
557
+ headers[key.toLowerCase()] = value;
558
+ }
559
+ }
560
+ }
561
+
562
+ return headers;
563
+ }
564
+
565
+ /**
566
+ * Extract pagination info from response headers
567
+ */
568
+ function extractPaginationInfo(
569
+ headers: Record<string, string>,
570
+ currentPagination?: PaginationConfig
571
+ ): PaginationInfo | undefined {
572
+ const info: PaginationInfo = {};
573
+ let hasPaginationInfo = false;
574
+
575
+ // Common total count headers
576
+ const totalCount = headers['x-total-count'] || headers['x-total'] || headers['total-count'];
577
+ if (totalCount) {
578
+ info.totalCount = parseInt(totalCount, 10);
579
+ hasPaginationInfo = true;
580
+ }
581
+
582
+ // Total pages
583
+ const totalPages = headers['x-total-pages'] || headers['x-page-count'];
584
+ if (totalPages) {
585
+ info.totalPages = parseInt(totalPages, 10);
586
+ hasPaginationInfo = true;
587
+ }
588
+
589
+ // Next cursor
590
+ const nextCursor = headers['x-next-cursor'] || headers['x-cursor-next'];
591
+ if (nextCursor) {
592
+ info.nextCursor = nextCursor;
593
+ info.hasMore = true;
594
+ hasPaginationInfo = true;
595
+ }
596
+
597
+ // Previous cursor
598
+ const prevCursor = headers['x-prev-cursor'] || headers['x-cursor-prev'];
599
+ if (prevCursor) {
600
+ info.prevCursor = prevCursor;
601
+ hasPaginationInfo = true;
602
+ }
603
+
604
+ // Has more indicator
605
+ const hasMore = headers['x-has-more'] || headers['x-has-next'];
606
+ if (hasMore) {
607
+ info.hasMore = hasMore.toLowerCase() === 'true' || hasMore === '1';
608
+ hasPaginationInfo = true;
609
+ }
610
+
611
+ // Parse Link header (RFC 5988)
612
+ const linkHeader = headers['link'];
613
+ if (linkHeader) {
614
+ const links = parseLinkHeader(linkHeader);
615
+ if (links.next) {
616
+ info.hasMore = true;
617
+ hasPaginationInfo = true;
618
+ }
619
+ }
620
+
621
+ // Include current pagination state
622
+ if (currentPagination) {
623
+ switch (currentPagination.type) {
624
+ case 'offset':
625
+ info.currentOffset = currentPagination.offset;
626
+ info.limit = currentPagination.limit;
627
+ break;
628
+ case 'cursor':
629
+ info.limit = currentPagination.limit;
630
+ break;
631
+ case 'page':
632
+ info.currentOffset = (currentPagination.page - 1) * currentPagination.pageSize;
633
+ info.limit = currentPagination.pageSize;
634
+ break;
635
+ case 'range':
636
+ info.currentOffset = currentPagination.start;
637
+ info.limit = currentPagination.end - currentPagination.start + 1;
638
+ break;
639
+ }
640
+ hasPaginationInfo = true;
641
+ }
642
+
643
+ // Calculate hasMore based on total count
644
+ if (info.hasMore === undefined && info.totalCount !== undefined &&
645
+ info.currentOffset !== undefined && info.limit !== undefined) {
646
+ info.hasMore = info.currentOffset + info.limit < info.totalCount;
647
+ }
648
+
649
+ return hasPaginationInfo ? info : undefined;
650
+ }
651
+
652
+ /**
653
+ * Parse RFC 5988 Link header
654
+ */
655
+ function parseLinkHeader(header: string): Record<string, string> {
656
+ const links: Record<string, string> = {};
657
+ const parts = header.split(',');
658
+
659
+ for (const part of parts) {
660
+ const match = part.match(/<([^>]+)>;\\s*rel="?([^";\\s]+)"?/);
661
+ if (match) {
662
+ links[match[2]] = match[1];
663
+ }
664
+ }
665
+
666
+ return links;
667
+ }
668
+
669
+ /**
670
+ * Create pagination helper functions for the response
671
+ */
672
+ function createPaginationHelpers<T, TContext extends HttpClientContext>(
673
+ currentConfig: TContext,
674
+ paginationInfo: PaginationInfo | undefined,
675
+ requestFn: (config: TContext) => Promise<HttpClientResponse<T>>
676
+ ): Pick<HttpClientResponse<T>, 'getNextPage' | 'getPrevPage' | 'hasNextPage' | 'hasPrevPage'> {
677
+ const helpers: Pick<HttpClientResponse<T>, 'getNextPage' | 'getPrevPage' | 'hasNextPage' | 'hasPrevPage'> = {};
678
+
679
+ if (!currentConfig.pagination) {
680
+ return helpers;
681
+ }
682
+
683
+ const pagination = currentConfig.pagination;
684
+
685
+ helpers.hasNextPage = () => {
686
+ if (paginationInfo?.hasMore !== undefined) return paginationInfo.hasMore;
687
+ if (paginationInfo?.nextCursor) return true;
688
+ if (paginationInfo?.totalCount !== undefined &&
689
+ paginationInfo.currentOffset !== undefined &&
690
+ paginationInfo.limit !== undefined) {
691
+ return paginationInfo.currentOffset + paginationInfo.limit < paginationInfo.totalCount;
692
+ }
693
+ return false;
694
+ };
695
+
696
+ helpers.hasPrevPage = () => {
697
+ if (paginationInfo?.prevCursor) return true;
698
+ if (paginationInfo?.currentOffset !== undefined) {
699
+ return paginationInfo.currentOffset > 0;
700
+ }
701
+ return false;
702
+ };
703
+
704
+ helpers.getNextPage = async () => {
705
+ let nextPagination: PaginationConfig;
706
+
707
+ switch (pagination.type) {
708
+ case 'offset':
709
+ nextPagination = { ...pagination, offset: pagination.offset + pagination.limit };
710
+ break;
711
+ case 'cursor':
712
+ if (!paginationInfo?.nextCursor) throw new Error('No next cursor available');
713
+ nextPagination = { ...pagination, cursor: paginationInfo.nextCursor };
714
+ break;
715
+ case 'page':
716
+ nextPagination = { ...pagination, page: pagination.page + 1 };
717
+ break;
718
+ case 'range':
719
+ const rangeSize = pagination.end - pagination.start + 1;
720
+ nextPagination = { ...pagination, start: pagination.end + 1, end: pagination.end + rangeSize };
721
+ break;
722
+ default:
723
+ throw new Error('Unsupported pagination type');
724
+ }
725
+
726
+ return requestFn({ ...currentConfig, pagination: nextPagination });
727
+ };
728
+
729
+ helpers.getPrevPage = async () => {
730
+ let prevPagination: PaginationConfig;
731
+
732
+ switch (pagination.type) {
733
+ case 'offset':
734
+ prevPagination = { ...pagination, offset: Math.max(0, pagination.offset - pagination.limit) };
735
+ break;
736
+ case 'cursor':
737
+ if (!paginationInfo?.prevCursor) throw new Error('No previous cursor available');
738
+ prevPagination = { ...pagination, cursor: paginationInfo.prevCursor };
739
+ break;
740
+ case 'page':
741
+ prevPagination = { ...pagination, page: Math.max(1, pagination.page - 1) };
742
+ break;
743
+ case 'range':
744
+ const size = pagination.end - pagination.start + 1;
745
+ const newStart = Math.max(0, pagination.start - size);
746
+ prevPagination = { ...pagination, start: newStart, end: newStart + size - 1 };
747
+ break;
748
+ default:
749
+ throw new Error('Unsupported pagination type');
750
+ }
751
+
752
+ return requestFn({ ...currentConfig, pagination: prevPagination });
753
+ };
754
+
755
+ return helpers;
756
+ }
757
+
758
+ /**
759
+ * Builds a URL with path parameters replaced
760
+ * @param server - Base server URL
761
+ * @param pathTemplate - Path template with {param} placeholders
762
+ * @param parameters - Parameter object with getChannelWithParameters method
763
+ */
764
+ function buildUrlWithParameters<T extends { getChannelWithParameters: (path: string) => string }>(
765
+ server: string,
766
+ pathTemplate: string,
767
+ parameters: T
768
+ ): string {
769
+ const path = parameters.getChannelWithParameters(pathTemplate);
770
+ return \`\${server}\${path}\`;
771
+ }
772
+
773
+ /**
774
+ * Extracts headers from a typed headers object and merges with additional headers
775
+ */
776
+ function applyTypedHeaders(
777
+ typedHeaders: { marshal: () => string } | undefined,
778
+ additionalHeaders: Record<string, string | string[]> | undefined
779
+ ): Record<string, string | string[]> {
780
+ const headers: Record<string, string | string[]> = {
781
+ 'Content-Type': 'application/json',
782
+ ...additionalHeaders
783
+ };
784
+
785
+ if (typedHeaders) {
786
+ // Parse the marshalled headers and merge them
787
+ const marshalledHeaders = JSON.parse(typedHeaders.marshal());
788
+ for (const [key, value] of Object.entries(marshalledHeaders)) {
789
+ headers[key] = value as string;
790
+ }
791
+ }
792
+
793
+ return headers;
794
+ }
795
+ ${requirements.oauth2 ? (0, security_1.renderOAuth2Helpers)() : (0, security_1.renderOAuth2Stubs)()}
796
+ // ============================================================================
797
+ // Generated HTTP Client Functions
798
+ // ============================================================================`;
799
+ }
800
+ exports.renderHttpCommonTypes = renderHttpCommonTypes;