@apso/cli 0.7.4 → 0.8.2

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 (203) hide show
  1. package/dist/autogen/index.d.ts +2 -0
  2. package/dist/autogen/index.js +3 -0
  3. package/dist/commands/server/new.d.ts +4 -1
  4. package/dist/commands/server/new.js +115 -22
  5. package/dist/commands/server/scaffold.d.ts +10 -0
  6. package/dist/commands/server/scaffold.js +200 -10
  7. package/dist/lib/api/client.d.ts +65 -0
  8. package/dist/lib/api/client.js +305 -0
  9. package/dist/lib/api/index.d.ts +8 -0
  10. package/dist/lib/api/index.js +22 -0
  11. package/dist/lib/api/services.d.ts +166 -0
  12. package/dist/lib/api/services.js +202 -0
  13. package/dist/lib/api/types.d.ts +212 -0
  14. package/dist/lib/api/types.js +7 -0
  15. package/dist/lib/apsorc-parser.d.ts +3 -0
  16. package/dist/lib/apsorc-parser.js +4 -0
  17. package/dist/lib/config/index.d.ts +8 -0
  18. package/dist/lib/config/index.js +17 -0
  19. package/dist/lib/config/manager.d.ts +127 -0
  20. package/dist/lib/config/manager.js +304 -0
  21. package/dist/lib/config/paths.d.ts +65 -0
  22. package/dist/lib/config/paths.js +127 -0
  23. package/dist/lib/config/types.d.ts +230 -0
  24. package/dist/lib/config/types.js +30 -0
  25. package/dist/lib/generators/base.d.ts +93 -0
  26. package/dist/lib/generators/base.js +90 -0
  27. package/dist/lib/generators/go.d.ts +37 -0
  28. package/dist/lib/generators/go.js +340 -0
  29. package/dist/lib/generators/index.d.ts +21 -0
  30. package/dist/lib/generators/index.js +51 -0
  31. package/dist/lib/generators/python.d.ts +21 -0
  32. package/dist/lib/generators/python.js +253 -0
  33. package/dist/lib/generators/typescript.d.ts +25 -0
  34. package/dist/lib/generators/typescript.js +373 -0
  35. package/dist/lib/index.d.ts +2 -0
  36. package/dist/lib/index.js +9 -1
  37. package/dist/lib/templates/entities/entity-col-timestamp.eta +9 -2
  38. package/dist/lib/templates/entities/entity-col-timestamptz.eta +9 -2
  39. package/dist/lib/templates/entities/entity.eta +18 -5
  40. package/dist/lib/templates/go/dto/dto-col-array.eta +7 -0
  41. package/dist/lib/templates/go/dto/dto-col-boolean.eta +7 -0
  42. package/dist/lib/templates/go/dto/dto-col-date.eta +7 -0
  43. package/dist/lib/templates/go/dto/dto-col-decimal.eta +7 -0
  44. package/dist/lib/templates/go/dto/dto-col-enum.eta +8 -0
  45. package/dist/lib/templates/go/dto/dto-col-float.eta +7 -0
  46. package/dist/lib/templates/go/dto/dto-col-integer.eta +7 -0
  47. package/dist/lib/templates/go/dto/dto-col-json.eta +7 -0
  48. package/dist/lib/templates/go/dto/dto-col-jsonb.eta +7 -0
  49. package/dist/lib/templates/go/dto/dto-col-numeric.eta +7 -0
  50. package/dist/lib/templates/go/dto/dto-col-string.eta +7 -0
  51. package/dist/lib/templates/go/dto/dto-col-text.eta +7 -0
  52. package/dist/lib/templates/go/dto/dto-col-timestamp.eta +7 -0
  53. package/dist/lib/templates/go/dto/dto-col-timestamptz.eta +7 -0
  54. package/dist/lib/templates/go/dto/dto-col-uuid.eta +7 -0
  55. package/dist/lib/templates/go/dto/dto-col-varchar.eta +7 -0
  56. package/dist/lib/templates/go/dto/dto.eta +78 -0
  57. package/dist/lib/templates/go/enums.eta +44 -0
  58. package/dist/lib/templates/go/handlers/handler.eta +212 -0
  59. package/dist/lib/templates/go/header.eta +3 -0
  60. package/dist/lib/templates/go/index-module.eta +53 -0
  61. package/dist/lib/templates/go/middleware/auth.eta +101 -0
  62. package/dist/lib/templates/go/models/model-col-array.eta +1 -0
  63. package/dist/lib/templates/go/models/model-col-boolean.eta +1 -0
  64. package/dist/lib/templates/go/models/model-col-date.eta +1 -0
  65. package/dist/lib/templates/go/models/model-col-decimal.eta +1 -0
  66. package/dist/lib/templates/go/models/model-col-enum.eta +2 -0
  67. package/dist/lib/templates/go/models/model-col-float.eta +1 -0
  68. package/dist/lib/templates/go/models/model-col-integer.eta +1 -0
  69. package/dist/lib/templates/go/models/model-col-json.eta +1 -0
  70. package/dist/lib/templates/go/models/model-col-jsonb.eta +1 -0
  71. package/dist/lib/templates/go/models/model-col-numeric.eta +1 -0
  72. package/dist/lib/templates/go/models/model-col-string.eta +1 -0
  73. package/dist/lib/templates/go/models/model-col-text.eta +1 -0
  74. package/dist/lib/templates/go/models/model-col-timestamp.eta +1 -0
  75. package/dist/lib/templates/go/models/model-col-timestamptz.eta +1 -0
  76. package/dist/lib/templates/go/models/model-col-uuid.eta +1 -0
  77. package/dist/lib/templates/go/models/model-col-varchar.eta +1 -0
  78. package/dist/lib/templates/go/models/model.eta +53 -0
  79. package/dist/lib/templates/go/services/service.eta +190 -0
  80. package/dist/lib/templates/python/enums.eta +10 -0
  81. package/dist/lib/templates/python/header.eta +6 -0
  82. package/dist/lib/templates/python/index-module.eta +18 -0
  83. package/dist/lib/templates/python/models/model-col-array.eta +4 -0
  84. package/dist/lib/templates/python/models/model-col-boolean.eta +5 -0
  85. package/dist/lib/templates/python/models/model-col-date.eta +4 -0
  86. package/dist/lib/templates/python/models/model-col-decimal.eta +4 -0
  87. package/dist/lib/templates/python/models/model-col-enum.eta +16 -0
  88. package/dist/lib/templates/python/models/model-col-float.eta +5 -0
  89. package/dist/lib/templates/python/models/model-col-integer.eta +6 -0
  90. package/dist/lib/templates/python/models/model-col-json.eta +4 -0
  91. package/dist/lib/templates/python/models/model-col-jsonb.eta +4 -0
  92. package/dist/lib/templates/python/models/model-col-numeric.eta +4 -0
  93. package/dist/lib/templates/python/models/model-col-string.eta +6 -0
  94. package/dist/lib/templates/python/models/model-col-text.eta +6 -0
  95. package/dist/lib/templates/python/models/model-col-timestamp.eta +11 -0
  96. package/dist/lib/templates/python/models/model-col-timestamptz.eta +11 -0
  97. package/dist/lib/templates/python/models/model-col-uuid.eta +5 -0
  98. package/dist/lib/templates/python/models/model-col-varchar.eta +6 -0
  99. package/dist/lib/templates/python/models/model.eta +124 -0
  100. package/dist/lib/templates/python/routers/router.eta +206 -0
  101. package/dist/lib/templates/python/schemas/schema-col-array.eta +1 -0
  102. package/dist/lib/templates/python/schemas/schema-col-boolean.eta +1 -0
  103. package/dist/lib/templates/python/schemas/schema-col-date.eta +1 -0
  104. package/dist/lib/templates/python/schemas/schema-col-decimal.eta +1 -0
  105. package/dist/lib/templates/python/schemas/schema-col-enum.eta +6 -0
  106. package/dist/lib/templates/python/schemas/schema-col-float.eta +1 -0
  107. package/dist/lib/templates/python/schemas/schema-col-integer.eta +1 -0
  108. package/dist/lib/templates/python/schemas/schema-col-json.eta +1 -0
  109. package/dist/lib/templates/python/schemas/schema-col-jsonb.eta +1 -0
  110. package/dist/lib/templates/python/schemas/schema-col-numeric.eta +1 -0
  111. package/dist/lib/templates/python/schemas/schema-col-string.eta +1 -0
  112. package/dist/lib/templates/python/schemas/schema-col-text.eta +1 -0
  113. package/dist/lib/templates/python/schemas/schema-col-timestamp.eta +1 -0
  114. package/dist/lib/templates/python/schemas/schema-col-timestamptz.eta +1 -0
  115. package/dist/lib/templates/python/schemas/schema-col-uuid.eta +1 -0
  116. package/dist/lib/templates/python/schemas/schema-col-varchar.eta +1 -0
  117. package/dist/lib/templates/python/schemas/schema.eta +87 -0
  118. package/dist/lib/templates/python/services/service.eta +163 -0
  119. package/dist/lib/templates/rest/controller-rest.eta +13 -12
  120. package/dist/lib/templates/rest/dto-rest.eta +173 -59
  121. package/dist/lib/types/generator.d.ts +241 -0
  122. package/dist/lib/types/generator.js +2 -0
  123. package/dist/lib/types/index.d.ts +1 -0
  124. package/dist/lib/utils/casing.d.ts +1 -0
  125. package/dist/lib/utils/casing.js +11 -1
  126. package/oclif.manifest.json +32 -3
  127. package/package.json +4 -2
  128. package/dist/lib/utils/relationships/parse.spec.d.ts +0 -1
  129. package/dist/lib/utils/relationships/parse.spec.js +0 -402
  130. package/dist/tests/templates/entities/types/array-template.spec.d.ts +0 -1
  131. package/dist/tests/templates/entities/types/array-template.spec.js +0 -82
  132. package/dist/tests/templates/entities/types/bigint-template.spec.d.ts +0 -1
  133. package/dist/tests/templates/entities/types/bigint-template.spec.js +0 -82
  134. package/dist/tests/templates/entities/types/boolean-template.spec.d.ts +0 -1
  135. package/dist/tests/templates/entities/types/boolean-template.spec.js +0 -77
  136. package/dist/tests/templates/entities/types/bytea-template.spec.d.ts +0 -1
  137. package/dist/tests/templates/entities/types/bytea-template.spec.js +0 -68
  138. package/dist/tests/templates/entities/types/char-template.spec.d.ts +0 -1
  139. package/dist/tests/templates/entities/types/char-template.spec.js +0 -68
  140. package/dist/tests/templates/entities/types/date-template.spec.d.ts +0 -1
  141. package/dist/tests/templates/entities/types/date-template.spec.js +0 -56
  142. package/dist/tests/templates/entities/types/decimal-field-validation.spec.d.ts +0 -1
  143. package/dist/tests/templates/entities/types/decimal-field-validation.spec.js +0 -100
  144. package/dist/tests/templates/entities/types/decimal-template.spec.d.ts +0 -1
  145. package/dist/tests/templates/entities/types/decimal-template.spec.js +0 -86
  146. package/dist/tests/templates/entities/types/double-template.spec.d.ts +0 -1
  147. package/dist/tests/templates/entities/types/double-template.spec.js +0 -70
  148. package/dist/tests/templates/entities/types/enum-template.spec.d.ts +0 -1
  149. package/dist/tests/templates/entities/types/enum-template.spec.js +0 -85
  150. package/dist/tests/templates/entities/types/float-template.spec.d.ts +0 -1
  151. package/dist/tests/templates/entities/types/float-template.spec.js +0 -70
  152. package/dist/tests/templates/entities/types/geometry-template.spec.d.ts +0 -1
  153. package/dist/tests/templates/entities/types/geometry-template.spec.js +0 -58
  154. package/dist/tests/templates/entities/types/inet-template.spec.d.ts +0 -1
  155. package/dist/tests/templates/entities/types/inet-template.spec.js +0 -69
  156. package/dist/tests/templates/entities/types/int4range-template.spec.d.ts +0 -1
  157. package/dist/tests/templates/entities/types/int4range-template.spec.js +0 -72
  158. package/dist/tests/templates/entities/types/integer-template.spec.d.ts +0 -1
  159. package/dist/tests/templates/entities/types/integer-template.spec.js +0 -79
  160. package/dist/tests/templates/entities/types/interval-template.spec.d.ts +0 -1
  161. package/dist/tests/templates/entities/types/interval-template.spec.js +0 -68
  162. package/dist/tests/templates/entities/types/json-plain-template.spec.d.ts +0 -1
  163. package/dist/tests/templates/entities/types/json-plain-template.spec.js +0 -54
  164. package/dist/tests/templates/entities/types/json-template.spec.d.ts +0 -1
  165. package/dist/tests/templates/entities/types/json-template.spec.js +0 -40
  166. package/dist/tests/templates/entities/types/jsonb-template.spec.d.ts +0 -1
  167. package/dist/tests/templates/entities/types/jsonb-template.spec.js +0 -40
  168. package/dist/tests/templates/entities/types/money-template.spec.d.ts +0 -1
  169. package/dist/tests/templates/entities/types/money-template.spec.js +0 -68
  170. package/dist/tests/templates/entities/types/numeric-template.spec.d.ts +0 -1
  171. package/dist/tests/templates/entities/types/numeric-template.spec.js +0 -84
  172. package/dist/tests/templates/entities/types/point-template.spec.d.ts +0 -1
  173. package/dist/tests/templates/entities/types/point-template.spec.js +0 -64
  174. package/dist/tests/templates/entities/types/polygon-template.spec.d.ts +0 -1
  175. package/dist/tests/templates/entities/types/polygon-template.spec.js +0 -70
  176. package/dist/tests/templates/entities/types/real-template.spec.d.ts +0 -1
  177. package/dist/tests/templates/entities/types/real-template.spec.js +0 -67
  178. package/dist/tests/templates/entities/types/serial-template.spec.d.ts +0 -1
  179. package/dist/tests/templates/entities/types/serial-template.spec.js +0 -113
  180. package/dist/tests/templates/entities/types/smallint-template.spec.d.ts +0 -1
  181. package/dist/tests/templates/entities/types/smallint-template.spec.js +0 -82
  182. package/dist/tests/templates/entities/types/string-template.spec.d.ts +0 -1
  183. package/dist/tests/templates/entities/types/string-template.spec.js +0 -111
  184. package/dist/tests/templates/entities/types/text-template.spec.d.ts +0 -1
  185. package/dist/tests/templates/entities/types/text-template.spec.js +0 -70
  186. package/dist/tests/templates/entities/types/time-template.spec.d.ts +0 -1
  187. package/dist/tests/templates/entities/types/time-template.spec.js +0 -68
  188. package/dist/tests/templates/entities/types/timestamp-template.spec.d.ts +0 -1
  189. package/dist/tests/templates/entities/types/timestamp-template.spec.js +0 -74
  190. package/dist/tests/templates/entities/types/timetz-template.spec.d.ts +0 -1
  191. package/dist/tests/templates/entities/types/timetz-template.spec.js +0 -68
  192. package/dist/tests/templates/entities/types/tsvector-template.spec.d.ts +0 -1
  193. package/dist/tests/templates/entities/types/tsvector-template.spec.js +0 -55
  194. package/dist/tests/templates/entities/types/uuid-template.spec.d.ts +0 -1
  195. package/dist/tests/templates/entities/types/uuid-template.spec.js +0 -82
  196. package/dist/tests/templates/entities/types/varchar-template.spec.d.ts +0 -1
  197. package/dist/tests/templates/entities/types/varchar-template.spec.js +0 -105
  198. package/dist/tests/templates/entities/types/xml-template.spec.d.ts +0 -1
  199. package/dist/tests/templates/entities/types/xml-template.spec.js +0 -55
  200. package/dist/tests/templates/entities/uuid-entity-template.spec.d.ts +0 -1
  201. package/dist/tests/templates/entities/uuid-entity-template.spec.js +0 -277
  202. package/dist/tests/utils/relationship-deduplication.spec.d.ts +0 -1
  203. package/dist/tests/utils/relationship-deduplication.spec.js +0 -98
@@ -0,0 +1,305 @@
1
+ "use strict";
2
+ /**
3
+ * Platform API Client
4
+ *
5
+ * HTTP client for making authenticated requests to the Apso platform.
6
+ * Features:
7
+ * - Automatic token refresh
8
+ * - Request/response interceptors
9
+ * - Retry with exponential backoff
10
+ * - Timeout handling
11
+ */
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.api = exports.apiRequest = exports.checkNetworkConnectivity = exports.ApiClientError = void 0;
14
+ const config_1 = require("../config");
15
+ /**
16
+ * Default request timeout in milliseconds
17
+ */
18
+ const DEFAULT_TIMEOUT = 30000;
19
+ /**
20
+ * Maximum retry attempts for failed requests
21
+ */
22
+ const MAX_RETRIES = 3;
23
+ /**
24
+ * Base delay for exponential backoff in milliseconds
25
+ */
26
+ const BACKOFF_BASE_DELAY = 1000;
27
+ /**
28
+ * Custom error class for API errors
29
+ */
30
+ class ApiClientError extends Error {
31
+ constructor(message, statusCode, details) {
32
+ super(message);
33
+ this.statusCode = statusCode;
34
+ this.details = details;
35
+ this.name = "ApiClientError";
36
+ }
37
+ /**
38
+ * Check if error is due to authentication failure
39
+ */
40
+ isAuthError() {
41
+ return this.statusCode === 401;
42
+ }
43
+ /**
44
+ * Check if error is a rate limit error
45
+ */
46
+ isRateLimitError() {
47
+ return this.statusCode === 429;
48
+ }
49
+ /**
50
+ * Check if error is a server error (5xx)
51
+ */
52
+ isServerError() {
53
+ return this.statusCode >= 500 && this.statusCode < 600;
54
+ }
55
+ }
56
+ exports.ApiClientError = ApiClientError;
57
+ /**
58
+ * Check if we're running in an environment with network access
59
+ */
60
+ async function checkNetworkConnectivity() {
61
+ try {
62
+ const config = config_1.globalConfig.read();
63
+ const controller = new AbortController();
64
+ const timeoutId = setTimeout(() => controller.abort(), 5000);
65
+ const response = await fetch(`${config.apiUrl}/health`, {
66
+ method: "HEAD",
67
+ signal: controller.signal,
68
+ });
69
+ clearTimeout(timeoutId);
70
+ return response.ok;
71
+ }
72
+ catch {
73
+ return false;
74
+ }
75
+ }
76
+ exports.checkNetworkConnectivity = checkNetworkConnectivity;
77
+ /**
78
+ * Sleep for a given number of milliseconds
79
+ */
80
+ function sleep(ms) {
81
+ return new Promise((resolve) => {
82
+ setTimeout(resolve, ms);
83
+ });
84
+ }
85
+ /**
86
+ * Calculate backoff delay with jitter
87
+ */
88
+ function getBackoffDelay(attempt) {
89
+ const delay = BACKOFF_BASE_DELAY * 2 ** attempt;
90
+ const jitter = Math.random() * 0.3 * delay;
91
+ return delay + jitter;
92
+ }
93
+ /**
94
+ * Build URL with query parameters
95
+ */
96
+ function buildUrl(baseUrl, path, params) {
97
+ const url = new URL(path, baseUrl);
98
+ if (params) {
99
+ Object.entries(params).forEach(([key, value]) => {
100
+ if (value !== undefined) {
101
+ url.searchParams.append(key, String(value));
102
+ }
103
+ });
104
+ }
105
+ return url.toString();
106
+ }
107
+ /**
108
+ * Refresh the access token using the refresh token
109
+ */
110
+ async function refreshAccessToken() {
111
+ const creds = config_1.credentials.read();
112
+ if (!creds) {
113
+ return false;
114
+ }
115
+ try {
116
+ const config = config_1.globalConfig.read();
117
+ const response = await fetch(`${config.apiUrl}/auth/cli/refresh`, {
118
+ method: "POST",
119
+ headers: {
120
+ "Content-Type": "application/json",
121
+ },
122
+ body: JSON.stringify({
123
+ refreshToken: creds.tokens.refreshToken,
124
+ }),
125
+ });
126
+ if (!response.ok) {
127
+ return false;
128
+ }
129
+ const data = (await response.json());
130
+ // Update stored credentials with new access token
131
+ config_1.credentials.write({
132
+ tokens: {
133
+ ...creds.tokens,
134
+ accessToken: data.accessToken,
135
+ expiresAt: new Date(Date.now() + data.expiresIn * 1000).toISOString(),
136
+ },
137
+ user: creds.user,
138
+ });
139
+ return true;
140
+ }
141
+ catch {
142
+ return false;
143
+ }
144
+ }
145
+ /**
146
+ * Make an authenticated request to the platform API
147
+ * Note: Sequential retries are intentional for proper backoff behavior
148
+ */
149
+ /* eslint-disable no-await-in-loop */
150
+ async function apiRequest(path, options = {}) {
151
+ const { method = "GET", body, params, headers = {}, timeout = DEFAULT_TIMEOUT, skipAuth = false, } = options;
152
+ const config = config_1.globalConfig.read();
153
+ const url = buildUrl(config.apiUrl, path, params);
154
+ // Build request headers
155
+ const requestHeaders = {
156
+ "Content-Type": "application/json",
157
+ "User-Agent": `apso-cli/${getCliVersion()}`,
158
+ ...headers,
159
+ };
160
+ // Add authentication if not skipped
161
+ if (!skipAuth) {
162
+ const creds = config_1.credentials.read();
163
+ if (!creds) {
164
+ throw new ApiClientError("Not authenticated. Run 'apso login' first.", 401);
165
+ }
166
+ // Check if token needs refresh
167
+ if (config_1.credentials.needsRefresh()) {
168
+ const refreshed = await refreshAccessToken();
169
+ if (!refreshed) {
170
+ throw new ApiClientError("Session expired. Please run 'apso login' again.", 401);
171
+ }
172
+ }
173
+ // Re-read credentials after potential refresh
174
+ const freshCreds = config_1.credentials.read();
175
+ if (freshCreds) {
176
+ requestHeaders.Authorization = `Bearer ${freshCreds.tokens.accessToken}`;
177
+ }
178
+ }
179
+ // Make request with retries
180
+ let lastError = null;
181
+ for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
182
+ try {
183
+ const controller = new AbortController();
184
+ const timeoutId = setTimeout(() => controller.abort(), timeout);
185
+ const response = await fetch(url, {
186
+ method,
187
+ headers: requestHeaders,
188
+ body: body ? JSON.stringify(body) : undefined,
189
+ signal: controller.signal,
190
+ });
191
+ clearTimeout(timeoutId);
192
+ // Handle response
193
+ if (response.ok) {
194
+ // Handle empty responses
195
+ const contentType = response.headers.get("content-type");
196
+ if ((contentType === null || contentType === void 0 ? void 0 : contentType.includes("application/json")) &&
197
+ response.status !== 204) {
198
+ return (await response.json());
199
+ }
200
+ return {};
201
+ }
202
+ // Parse error response
203
+ let errorData;
204
+ try {
205
+ errorData = await response.json();
206
+ }
207
+ catch {
208
+ errorData = {
209
+ statusCode: response.status,
210
+ message: response.statusText,
211
+ };
212
+ }
213
+ // Handle 401 - try refresh once
214
+ if (response.status === 401 && attempt === 0 && !skipAuth) {
215
+ const refreshed = await refreshAccessToken();
216
+ if (refreshed) {
217
+ // Retry with new token
218
+ continue;
219
+ }
220
+ throw new ApiClientError("Session expired. Please run 'apso login' again.", 401);
221
+ }
222
+ // Handle rate limiting
223
+ if (response.status === 429) {
224
+ const retryAfter = response.headers.get("retry-after");
225
+ const waitTime = retryAfter
226
+ ? Number.parseInt(retryAfter, 10) * 1000
227
+ : getBackoffDelay(attempt);
228
+ await sleep(waitTime);
229
+ continue;
230
+ }
231
+ // Handle server errors with retry
232
+ if (response.status >= 500) {
233
+ lastError = new ApiClientError(errorData.message || "Server error", response.status, errorData.details);
234
+ await sleep(getBackoffDelay(attempt));
235
+ continue;
236
+ }
237
+ // Client errors - don't retry
238
+ throw new ApiClientError(errorData.message || "Request failed", response.status, errorData.details);
239
+ }
240
+ catch (error) {
241
+ if (error instanceof ApiClientError) {
242
+ throw error;
243
+ }
244
+ // Handle abort/timeout
245
+ if (error instanceof Error && error.name === "AbortError") {
246
+ lastError = new ApiClientError("Request timeout", 408);
247
+ continue;
248
+ }
249
+ // Network errors
250
+ lastError = new ApiClientError(error instanceof Error ? error.message : "Network error", 0);
251
+ await sleep(getBackoffDelay(attempt));
252
+ }
253
+ }
254
+ throw lastError || new ApiClientError("Request failed after retries", 500);
255
+ }
256
+ exports.apiRequest = apiRequest;
257
+ /* eslint-enable no-await-in-loop */
258
+ /**
259
+ * Get CLI version for User-Agent header
260
+ */
261
+ function getCliVersion() {
262
+ try {
263
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
264
+ const pkg = require("../../../package.json");
265
+ return pkg.version;
266
+ }
267
+ catch {
268
+ return "0.0.0";
269
+ }
270
+ }
271
+ /**
272
+ * Platform API client with typed methods
273
+ */
274
+ exports.api = {
275
+ /**
276
+ * Make a GET request
277
+ */
278
+ get(path, options) {
279
+ return apiRequest(path, { ...options, method: "GET" });
280
+ },
281
+ /**
282
+ * Make a POST request
283
+ */
284
+ post(path, body, options) {
285
+ return apiRequest(path, { ...options, method: "POST", body });
286
+ },
287
+ /**
288
+ * Make a PUT request
289
+ */
290
+ put(path, body, options) {
291
+ return apiRequest(path, { ...options, method: "PUT", body });
292
+ },
293
+ /**
294
+ * Make a PATCH request
295
+ */
296
+ patch(path, body, options) {
297
+ return apiRequest(path, { ...options, method: "PATCH", body });
298
+ },
299
+ /**
300
+ * Make a DELETE request
301
+ */
302
+ delete(path, options) {
303
+ return apiRequest(path, { ...options, method: "DELETE" });
304
+ },
305
+ };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Platform API Module
3
+ *
4
+ * Exports API client, types, and service functions.
5
+ */
6
+ export * from "./types";
7
+ export { api, apiRequest, ApiClientError, checkNetworkConnectivity } from "./client";
8
+ export { authApi, workspacesApi, servicesApi, schemaApi, buildApi, githubApi, } from "./services";
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ /**
3
+ * Platform API Module
4
+ *
5
+ * Exports API client, types, and service functions.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.githubApi = exports.buildApi = exports.schemaApi = exports.servicesApi = exports.workspacesApi = exports.authApi = exports.checkNetworkConnectivity = exports.ApiClientError = exports.apiRequest = exports.api = void 0;
9
+ const tslib_1 = require("tslib");
10
+ tslib_1.__exportStar(require("./types"), exports);
11
+ var client_1 = require("./client");
12
+ Object.defineProperty(exports, "api", { enumerable: true, get: function () { return client_1.api; } });
13
+ Object.defineProperty(exports, "apiRequest", { enumerable: true, get: function () { return client_1.apiRequest; } });
14
+ Object.defineProperty(exports, "ApiClientError", { enumerable: true, get: function () { return client_1.ApiClientError; } });
15
+ Object.defineProperty(exports, "checkNetworkConnectivity", { enumerable: true, get: function () { return client_1.checkNetworkConnectivity; } });
16
+ var services_1 = require("./services");
17
+ Object.defineProperty(exports, "authApi", { enumerable: true, get: function () { return services_1.authApi; } });
18
+ Object.defineProperty(exports, "workspacesApi", { enumerable: true, get: function () { return services_1.workspacesApi; } });
19
+ Object.defineProperty(exports, "servicesApi", { enumerable: true, get: function () { return services_1.servicesApi; } });
20
+ Object.defineProperty(exports, "schemaApi", { enumerable: true, get: function () { return services_1.schemaApi; } });
21
+ Object.defineProperty(exports, "buildApi", { enumerable: true, get: function () { return services_1.buildApi; } });
22
+ Object.defineProperty(exports, "githubApi", { enumerable: true, get: function () { return services_1.githubApi; } });
@@ -0,0 +1,166 @@
1
+ /**
2
+ * Platform API Services
3
+ *
4
+ * Typed API methods for interacting with platform resources.
5
+ */
6
+ import { UserProfile, Workspace, Service, ServiceSchema, GitHubRepo, GitHubConnection, BuildStatus, PaginatedResponse, TokenExchangeResponse } from "./types";
7
+ /**
8
+ * Authentication API
9
+ */
10
+ export declare const authApi: {
11
+ /**
12
+ * Exchange OAuth authorization code for tokens
13
+ */
14
+ exchangeCode(code: string): Promise<TokenExchangeResponse>;
15
+ /**
16
+ * Get current user profile
17
+ */
18
+ getProfile(): Promise<UserProfile>;
19
+ /**
20
+ * Revoke current session
21
+ */
22
+ logout(): Promise<void>;
23
+ };
24
+ /**
25
+ * Workspaces API
26
+ */
27
+ export declare const workspacesApi: {
28
+ /**
29
+ * List all workspaces the user has access to
30
+ */
31
+ list(): Promise<Workspace[]>;
32
+ /**
33
+ * Get a specific workspace by slug
34
+ */
35
+ get(slug: string): Promise<Workspace>;
36
+ /**
37
+ * Get workspace by ID
38
+ */
39
+ getById(id: string): Promise<Workspace>;
40
+ };
41
+ /**
42
+ * Services API
43
+ */
44
+ export declare const servicesApi: {
45
+ /**
46
+ * List all services in a workspace
47
+ */
48
+ list(workspaceSlug: string, options?: {
49
+ status?: string;
50
+ page?: number;
51
+ pageSize?: number;
52
+ }): Promise<PaginatedResponse<Service>>;
53
+ /**
54
+ * Get a specific service by slug
55
+ */
56
+ get(workspaceSlug: string, serviceSlug: string): Promise<Service>;
57
+ /**
58
+ * Get service by ID
59
+ */
60
+ getById(id: string): Promise<Service>;
61
+ /**
62
+ * Create a new service
63
+ */
64
+ create(workspaceSlug: string, data: {
65
+ name: string;
66
+ slug?: string;
67
+ description?: string;
68
+ githubRepo?: string;
69
+ githubBranch?: string;
70
+ }): Promise<Service>;
71
+ /**
72
+ * Update a service
73
+ */
74
+ update(workspaceSlug: string, serviceSlug: string, data: Partial<{
75
+ name: string;
76
+ description: string;
77
+ githubRepo: string;
78
+ githubBranch: string;
79
+ }>): Promise<Service>;
80
+ /**
81
+ * Delete a service
82
+ */
83
+ delete(workspaceSlug: string, serviceSlug: string): Promise<void>;
84
+ };
85
+ /**
86
+ * Schema API
87
+ */
88
+ export declare const schemaApi: {
89
+ /**
90
+ * Get the current schema for a service
91
+ */
92
+ get(workspaceSlug: string, serviceSlug: string): Promise<ServiceSchema>;
93
+ /**
94
+ * Get schema by service ID
95
+ */
96
+ getByServiceId(serviceId: string): Promise<ServiceSchema>;
97
+ /**
98
+ * Update the schema for a service (push)
99
+ */
100
+ update(workspaceSlug: string, serviceSlug: string, schema: Omit<ServiceSchema, "id" | "serviceId" | "version" | "createdAt" | "updatedAt">): Promise<ServiceSchema>;
101
+ /**
102
+ * Validate a schema without saving
103
+ */
104
+ validate(workspaceSlug: string, serviceSlug: string, schema: Omit<ServiceSchema, "id" | "serviceId" | "version" | "createdAt" | "updatedAt">): Promise<{
105
+ valid: boolean;
106
+ errors: string[];
107
+ }>;
108
+ /**
109
+ * Get schema diff between local and remote
110
+ */
111
+ diff(workspaceSlug: string, serviceSlug: string, localSchema: Omit<ServiceSchema, "id" | "serviceId" | "version" | "createdAt" | "updatedAt">): Promise<{
112
+ hasChanges: boolean;
113
+ added: string[];
114
+ removed: string[];
115
+ modified: string[];
116
+ }>;
117
+ };
118
+ /**
119
+ * Build API
120
+ */
121
+ export declare const buildApi: {
122
+ /**
123
+ * Trigger a build for a service
124
+ */
125
+ trigger(workspaceSlug: string, serviceSlug: string): Promise<BuildStatus>;
126
+ /**
127
+ * Get build status
128
+ */
129
+ getStatus(buildId: string): Promise<BuildStatus>;
130
+ /**
131
+ * Get latest build for a service
132
+ */
133
+ getLatest(workspaceSlug: string, serviceSlug: string): Promise<BuildStatus | null>;
134
+ /**
135
+ * Poll for build completion
136
+ * Note: Sequential polling is intentional for proper status checking
137
+ */
138
+ waitForCompletion(buildId: string, options?: {
139
+ maxWait?: number | undefined;
140
+ pollInterval?: number | undefined;
141
+ onProgress?: ((status: BuildStatus) => void) | undefined;
142
+ } | undefined): Promise<BuildStatus>;
143
+ };
144
+ /**
145
+ * GitHub API
146
+ */
147
+ export declare const githubApi: {
148
+ /**
149
+ * Get GitHub connection status for a workspace
150
+ */
151
+ getConnection(workspaceSlug: string): Promise<GitHubConnection>;
152
+ /**
153
+ * List available GitHub repositories
154
+ */
155
+ listRepos(workspaceSlug: string, options?: {
156
+ page?: number;
157
+ pageSize?: number;
158
+ search?: string;
159
+ }): Promise<PaginatedResponse<GitHubRepo>>;
160
+ /**
161
+ * Get OAuth URL for GitHub connection
162
+ */
163
+ getConnectUrl(workspaceSlug: string): Promise<{
164
+ url: string;
165
+ }>;
166
+ };
@@ -0,0 +1,202 @@
1
+ "use strict";
2
+ /**
3
+ * Platform API Services
4
+ *
5
+ * Typed API methods for interacting with platform resources.
6
+ */
7
+ Object.defineProperty(exports, "__esModule", { value: true });
8
+ exports.githubApi = exports.buildApi = exports.schemaApi = exports.servicesApi = exports.workspacesApi = exports.authApi = void 0;
9
+ const client_1 = require("./client");
10
+ /**
11
+ * Authentication API
12
+ */
13
+ exports.authApi = {
14
+ /**
15
+ * Exchange OAuth authorization code for tokens
16
+ */
17
+ exchangeCode(code) {
18
+ return client_1.api.post("/auth/cli/exchange", { code }, { skipAuth: true });
19
+ },
20
+ /**
21
+ * Get current user profile
22
+ */
23
+ getProfile() {
24
+ return client_1.api.get("/auth/me");
25
+ },
26
+ /**
27
+ * Revoke current session
28
+ */
29
+ logout() {
30
+ return client_1.api.post("/auth/cli/logout");
31
+ },
32
+ };
33
+ /**
34
+ * Workspaces API
35
+ */
36
+ exports.workspacesApi = {
37
+ /**
38
+ * List all workspaces the user has access to
39
+ */
40
+ list() {
41
+ return client_1.api.get("/workspaces");
42
+ },
43
+ /**
44
+ * Get a specific workspace by slug
45
+ */
46
+ get(slug) {
47
+ return client_1.api.get(`/workspaces/${slug}`);
48
+ },
49
+ /**
50
+ * Get workspace by ID
51
+ */
52
+ getById(id) {
53
+ return client_1.api.get(`/workspaces/by-id/${id}`);
54
+ },
55
+ };
56
+ /**
57
+ * Services API
58
+ */
59
+ exports.servicesApi = {
60
+ /**
61
+ * List all services in a workspace
62
+ */
63
+ list(workspaceSlug, options) {
64
+ return client_1.api.get(`/workspaces/${workspaceSlug}/services`, { params: options });
65
+ },
66
+ /**
67
+ * Get a specific service by slug
68
+ */
69
+ get(workspaceSlug, serviceSlug) {
70
+ return client_1.api.get(`/workspaces/${workspaceSlug}/services/${serviceSlug}`);
71
+ },
72
+ /**
73
+ * Get service by ID
74
+ */
75
+ getById(id) {
76
+ return client_1.api.get(`/services/${id}`);
77
+ },
78
+ /**
79
+ * Create a new service
80
+ */
81
+ create(workspaceSlug, data) {
82
+ return client_1.api.post(`/workspaces/${workspaceSlug}/services`, data);
83
+ },
84
+ /**
85
+ * Update a service
86
+ */
87
+ update(workspaceSlug, serviceSlug, data) {
88
+ return client_1.api.patch(`/workspaces/${workspaceSlug}/services/${serviceSlug}`, data);
89
+ },
90
+ /**
91
+ * Delete a service
92
+ */
93
+ delete(workspaceSlug, serviceSlug) {
94
+ return client_1.api.delete(`/workspaces/${workspaceSlug}/services/${serviceSlug}`);
95
+ },
96
+ };
97
+ /**
98
+ * Schema API
99
+ */
100
+ exports.schemaApi = {
101
+ /**
102
+ * Get the current schema for a service
103
+ */
104
+ get(workspaceSlug, serviceSlug) {
105
+ return client_1.api.get(`/workspaces/${workspaceSlug}/services/${serviceSlug}/schema`);
106
+ },
107
+ /**
108
+ * Get schema by service ID
109
+ */
110
+ getByServiceId(serviceId) {
111
+ return client_1.api.get(`/services/${serviceId}/schema`);
112
+ },
113
+ /**
114
+ * Update the schema for a service (push)
115
+ */
116
+ update(workspaceSlug, serviceSlug, schema) {
117
+ return client_1.api.put(`/workspaces/${workspaceSlug}/services/${serviceSlug}/schema`, schema);
118
+ },
119
+ /**
120
+ * Validate a schema without saving
121
+ */
122
+ validate(workspaceSlug, serviceSlug, schema) {
123
+ return client_1.api.post(`/workspaces/${workspaceSlug}/services/${serviceSlug}/schema/validate`, schema);
124
+ },
125
+ /**
126
+ * Get schema diff between local and remote
127
+ */
128
+ diff(workspaceSlug, serviceSlug, localSchema) {
129
+ return client_1.api.post(`/workspaces/${workspaceSlug}/services/${serviceSlug}/schema/diff`, localSchema);
130
+ },
131
+ };
132
+ /**
133
+ * Build API
134
+ */
135
+ exports.buildApi = {
136
+ /**
137
+ * Trigger a build for a service
138
+ */
139
+ trigger(workspaceSlug, serviceSlug) {
140
+ return client_1.api.post(`/workspaces/${workspaceSlug}/services/${serviceSlug}/build`);
141
+ },
142
+ /**
143
+ * Get build status
144
+ */
145
+ getStatus(buildId) {
146
+ return client_1.api.get(`/builds/${buildId}`);
147
+ },
148
+ /**
149
+ * Get latest build for a service
150
+ */
151
+ getLatest(workspaceSlug, serviceSlug) {
152
+ return client_1.api.get(`/workspaces/${workspaceSlug}/services/${serviceSlug}/build/latest`);
153
+ },
154
+ /**
155
+ * Poll for build completion
156
+ * Note: Sequential polling is intentional for proper status checking
157
+ */
158
+ async waitForCompletion(buildId, options) {
159
+ var _a, _b;
160
+ const maxWait = (_a = options === null || options === void 0 ? void 0 : options.maxWait) !== null && _a !== void 0 ? _a : 300000; // 5 minutes default
161
+ const pollInterval = (_b = options === null || options === void 0 ? void 0 : options.pollInterval) !== null && _b !== void 0 ? _b : 3000; // 3 seconds
162
+ const startTime = Date.now();
163
+ /* eslint-disable no-await-in-loop */
164
+ while (Date.now() - startTime < maxWait) {
165
+ const status = await this.getStatus(buildId);
166
+ if (options === null || options === void 0 ? void 0 : options.onProgress) {
167
+ options.onProgress(status);
168
+ }
169
+ if (status.status === "success" || status.status === "failed") {
170
+ return status;
171
+ }
172
+ await new Promise((resolve) => {
173
+ setTimeout(resolve, pollInterval);
174
+ });
175
+ }
176
+ /* eslint-enable no-await-in-loop */
177
+ throw new Error("Build timed out");
178
+ },
179
+ };
180
+ /**
181
+ * GitHub API
182
+ */
183
+ exports.githubApi = {
184
+ /**
185
+ * Get GitHub connection status for a workspace
186
+ */
187
+ getConnection(workspaceSlug) {
188
+ return client_1.api.get(`/workspaces/${workspaceSlug}/github/connection`);
189
+ },
190
+ /**
191
+ * List available GitHub repositories
192
+ */
193
+ listRepos(workspaceSlug, options) {
194
+ return client_1.api.get(`/workspaces/${workspaceSlug}/github/repos`, { params: options });
195
+ },
196
+ /**
197
+ * Get OAuth URL for GitHub connection
198
+ */
199
+ getConnectUrl(workspaceSlug) {
200
+ return client_1.api.get(`/workspaces/${workspaceSlug}/github/connect-url`);
201
+ },
202
+ };