@apso/cli 0.7.4 → 0.8.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/autogen/index.d.ts +2 -0
- package/dist/autogen/index.js +3 -0
- package/dist/commands/server/new.d.ts +4 -1
- package/dist/commands/server/new.js +115 -22
- package/dist/commands/server/scaffold.d.ts +10 -0
- package/dist/commands/server/scaffold.js +200 -10
- package/dist/lib/api/client.d.ts +65 -0
- package/dist/lib/api/client.js +305 -0
- package/dist/lib/api/index.d.ts +8 -0
- package/dist/lib/api/index.js +22 -0
- package/dist/lib/api/services.d.ts +166 -0
- package/dist/lib/api/services.js +202 -0
- package/dist/lib/api/types.d.ts +212 -0
- package/dist/lib/api/types.js +7 -0
- package/dist/lib/apsorc-parser.d.ts +3 -0
- package/dist/lib/apsorc-parser.js +4 -0
- package/dist/lib/config/index.d.ts +8 -0
- package/dist/lib/config/index.js +17 -0
- package/dist/lib/config/manager.d.ts +127 -0
- package/dist/lib/config/manager.js +304 -0
- package/dist/lib/config/paths.d.ts +65 -0
- package/dist/lib/config/paths.js +127 -0
- package/dist/lib/config/types.d.ts +230 -0
- package/dist/lib/config/types.js +30 -0
- package/dist/lib/generators/base.d.ts +93 -0
- package/dist/lib/generators/base.js +90 -0
- package/dist/lib/generators/go.d.ts +37 -0
- package/dist/lib/generators/go.js +340 -0
- package/dist/lib/generators/index.d.ts +21 -0
- package/dist/lib/generators/index.js +51 -0
- package/dist/lib/generators/python.d.ts +21 -0
- package/dist/lib/generators/python.js +253 -0
- package/dist/lib/generators/typescript.d.ts +25 -0
- package/dist/lib/generators/typescript.js +373 -0
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/index.js +9 -1
- package/dist/lib/templates/entities/entity-col-timestamp.eta +9 -2
- package/dist/lib/templates/entities/entity-col-timestamptz.eta +9 -2
- package/dist/lib/templates/entities/entity.eta +16 -3
- package/dist/lib/templates/go/dto/dto-col-array.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-boolean.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-date.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-decimal.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-enum.eta +8 -0
- package/dist/lib/templates/go/dto/dto-col-float.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-integer.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-json.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-jsonb.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-numeric.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-string.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-text.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-timestamp.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-timestamptz.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-uuid.eta +7 -0
- package/dist/lib/templates/go/dto/dto-col-varchar.eta +7 -0
- package/dist/lib/templates/go/dto/dto.eta +78 -0
- package/dist/lib/templates/go/enums.eta +44 -0
- package/dist/lib/templates/go/handlers/handler.eta +212 -0
- package/dist/lib/templates/go/header.eta +3 -0
- package/dist/lib/templates/go/index-module.eta +53 -0
- package/dist/lib/templates/go/middleware/auth.eta +101 -0
- package/dist/lib/templates/go/models/model-col-array.eta +1 -0
- package/dist/lib/templates/go/models/model-col-boolean.eta +1 -0
- package/dist/lib/templates/go/models/model-col-date.eta +1 -0
- package/dist/lib/templates/go/models/model-col-decimal.eta +1 -0
- package/dist/lib/templates/go/models/model-col-enum.eta +2 -0
- package/dist/lib/templates/go/models/model-col-float.eta +1 -0
- package/dist/lib/templates/go/models/model-col-integer.eta +1 -0
- package/dist/lib/templates/go/models/model-col-json.eta +1 -0
- package/dist/lib/templates/go/models/model-col-jsonb.eta +1 -0
- package/dist/lib/templates/go/models/model-col-numeric.eta +1 -0
- package/dist/lib/templates/go/models/model-col-string.eta +1 -0
- package/dist/lib/templates/go/models/model-col-text.eta +1 -0
- package/dist/lib/templates/go/models/model-col-timestamp.eta +1 -0
- package/dist/lib/templates/go/models/model-col-timestamptz.eta +1 -0
- package/dist/lib/templates/go/models/model-col-uuid.eta +1 -0
- package/dist/lib/templates/go/models/model-col-varchar.eta +1 -0
- package/dist/lib/templates/go/models/model.eta +53 -0
- package/dist/lib/templates/go/services/service.eta +190 -0
- package/dist/lib/templates/python/enums.eta +10 -0
- package/dist/lib/templates/python/header.eta +6 -0
- package/dist/lib/templates/python/index-module.eta +18 -0
- package/dist/lib/templates/python/models/model-col-array.eta +4 -0
- package/dist/lib/templates/python/models/model-col-boolean.eta +5 -0
- package/dist/lib/templates/python/models/model-col-date.eta +4 -0
- package/dist/lib/templates/python/models/model-col-decimal.eta +4 -0
- package/dist/lib/templates/python/models/model-col-enum.eta +16 -0
- package/dist/lib/templates/python/models/model-col-float.eta +5 -0
- package/dist/lib/templates/python/models/model-col-integer.eta +6 -0
- package/dist/lib/templates/python/models/model-col-json.eta +4 -0
- package/dist/lib/templates/python/models/model-col-jsonb.eta +4 -0
- package/dist/lib/templates/python/models/model-col-numeric.eta +4 -0
- package/dist/lib/templates/python/models/model-col-string.eta +6 -0
- package/dist/lib/templates/python/models/model-col-text.eta +6 -0
- package/dist/lib/templates/python/models/model-col-timestamp.eta +11 -0
- package/dist/lib/templates/python/models/model-col-timestamptz.eta +11 -0
- package/dist/lib/templates/python/models/model-col-uuid.eta +5 -0
- package/dist/lib/templates/python/models/model-col-varchar.eta +6 -0
- package/dist/lib/templates/python/models/model.eta +124 -0
- package/dist/lib/templates/python/routers/router.eta +206 -0
- package/dist/lib/templates/python/schemas/schema-col-array.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-boolean.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-date.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-decimal.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-enum.eta +6 -0
- package/dist/lib/templates/python/schemas/schema-col-float.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-integer.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-json.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-jsonb.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-numeric.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-string.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-text.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-timestamp.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-timestamptz.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-uuid.eta +1 -0
- package/dist/lib/templates/python/schemas/schema-col-varchar.eta +1 -0
- package/dist/lib/templates/python/schemas/schema.eta +87 -0
- package/dist/lib/templates/python/services/service.eta +163 -0
- package/dist/lib/templates/rest/controller-rest.eta +13 -12
- package/dist/lib/templates/rest/dto-rest.eta +173 -59
- package/dist/lib/types/generator.d.ts +241 -0
- package/dist/lib/types/generator.js +2 -0
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/utils/casing.d.ts +1 -0
- package/dist/lib/utils/casing.js +11 -1
- package/oclif.manifest.json +32 -3
- package/package.json +4 -2
- package/dist/lib/utils/relationships/parse.spec.d.ts +0 -1
- package/dist/lib/utils/relationships/parse.spec.js +0 -402
- package/dist/tests/templates/entities/types/array-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/array-template.spec.js +0 -82
- package/dist/tests/templates/entities/types/bigint-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/bigint-template.spec.js +0 -82
- package/dist/tests/templates/entities/types/boolean-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/boolean-template.spec.js +0 -77
- package/dist/tests/templates/entities/types/bytea-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/bytea-template.spec.js +0 -68
- package/dist/tests/templates/entities/types/char-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/char-template.spec.js +0 -68
- package/dist/tests/templates/entities/types/date-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/date-template.spec.js +0 -56
- package/dist/tests/templates/entities/types/decimal-field-validation.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/decimal-field-validation.spec.js +0 -100
- package/dist/tests/templates/entities/types/decimal-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/decimal-template.spec.js +0 -86
- package/dist/tests/templates/entities/types/double-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/double-template.spec.js +0 -70
- package/dist/tests/templates/entities/types/enum-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/enum-template.spec.js +0 -85
- package/dist/tests/templates/entities/types/float-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/float-template.spec.js +0 -70
- package/dist/tests/templates/entities/types/geometry-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/geometry-template.spec.js +0 -58
- package/dist/tests/templates/entities/types/inet-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/inet-template.spec.js +0 -69
- package/dist/tests/templates/entities/types/int4range-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/int4range-template.spec.js +0 -72
- package/dist/tests/templates/entities/types/integer-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/integer-template.spec.js +0 -79
- package/dist/tests/templates/entities/types/interval-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/interval-template.spec.js +0 -68
- package/dist/tests/templates/entities/types/json-plain-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/json-plain-template.spec.js +0 -54
- package/dist/tests/templates/entities/types/json-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/json-template.spec.js +0 -40
- package/dist/tests/templates/entities/types/jsonb-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/jsonb-template.spec.js +0 -40
- package/dist/tests/templates/entities/types/money-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/money-template.spec.js +0 -68
- package/dist/tests/templates/entities/types/numeric-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/numeric-template.spec.js +0 -84
- package/dist/tests/templates/entities/types/point-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/point-template.spec.js +0 -64
- package/dist/tests/templates/entities/types/polygon-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/polygon-template.spec.js +0 -70
- package/dist/tests/templates/entities/types/real-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/real-template.spec.js +0 -67
- package/dist/tests/templates/entities/types/serial-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/serial-template.spec.js +0 -113
- package/dist/tests/templates/entities/types/smallint-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/smallint-template.spec.js +0 -82
- package/dist/tests/templates/entities/types/string-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/string-template.spec.js +0 -111
- package/dist/tests/templates/entities/types/text-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/text-template.spec.js +0 -70
- package/dist/tests/templates/entities/types/time-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/time-template.spec.js +0 -68
- package/dist/tests/templates/entities/types/timestamp-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/timestamp-template.spec.js +0 -74
- package/dist/tests/templates/entities/types/timetz-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/timetz-template.spec.js +0 -68
- package/dist/tests/templates/entities/types/tsvector-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/tsvector-template.spec.js +0 -55
- package/dist/tests/templates/entities/types/uuid-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/uuid-template.spec.js +0 -82
- package/dist/tests/templates/entities/types/varchar-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/varchar-template.spec.js +0 -105
- package/dist/tests/templates/entities/types/xml-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/types/xml-template.spec.js +0 -55
- package/dist/tests/templates/entities/uuid-entity-template.spec.d.ts +0 -1
- package/dist/tests/templates/entities/uuid-entity-template.spec.js +0 -277
- package/dist/tests/utils/relationship-deduplication.spec.d.ts +0 -1
- 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
|
+
};
|