@typeship-ax/cli 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +31 -0
- package/README.md +26 -9
- package/api.json +3509 -800
- package/api.md +444 -494
- package/dist/api-identity.d.ts +40 -0
- package/dist/api-identity.d.ts.map +1 -0
- package/dist/api-identity.js +128 -0
- package/dist/auth-profiles.d.ts +30 -0
- package/dist/auth-profiles.d.ts.map +1 -0
- package/dist/auth-profiles.js +138 -0
- package/dist/cli.js +522 -355
- package/dist/console-login-check.d.ts +21 -0
- package/dist/console-login-check.d.ts.map +1 -0
- package/dist/console-login-check.js +107 -0
- package/dist/console-login-contract.d.ts +45 -0
- package/dist/console-login-contract.d.ts.map +1 -0
- package/dist/console-login-contract.js +40 -0
- package/dist/core/http.d.ts +17 -2
- package/dist/core/http.d.ts.map +1 -1
- package/dist/core/http.js +78 -17
- package/dist/credential-storage.d.ts +24 -0
- package/dist/credential-storage.d.ts.map +1 -0
- package/dist/credential-storage.js +207 -0
- package/dist/docs.d.ts +25 -0
- package/dist/docs.d.ts.map +1 -1
- package/dist/docs.js +144 -0
- package/dist/errors.d.ts +18 -10
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +24 -14
- package/dist/index.d.ts +10 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -4
- package/dist/named-credentials.d.ts +21 -0
- package/dist/named-credentials.d.ts.map +1 -0
- package/dist/named-credentials.js +86 -0
- package/dist/oauth-login.d.ts +39 -0
- package/dist/oauth-login.d.ts.map +1 -0
- package/dist/oauth-login.js +171 -0
- package/dist/oauth-request.d.ts +21 -0
- package/dist/oauth-request.d.ts.map +1 -0
- package/dist/oauth-request.js +119 -0
- package/dist/oauth-session.d.ts +106 -0
- package/dist/oauth-session.d.ts.map +1 -0
- package/dist/oauth-session.js +244 -0
- package/dist/ops.d.ts +14 -1
- package/dist/ops.d.ts.map +1 -1
- package/dist/ops.js +34 -30
- package/dist/polling-login.d.ts +57 -0
- package/dist/polling-login.d.ts.map +1 -0
- package/dist/polling-login.js +204 -0
- package/dist/resources/account.d.ts +2 -2
- package/dist/resources/account.d.ts.map +1 -1
- package/dist/resources/account.js +1 -0
- package/dist/resources/api-keys.d.ts +3 -3
- package/dist/resources/api-keys.d.ts.map +1 -1
- package/dist/resources/api-keys.js +2 -0
- package/dist/resources/definition-revisions.d.ts +5 -5
- package/dist/resources/definition-revisions.d.ts.map +1 -1
- package/dist/resources/definition-revisions.js +4 -0
- package/dist/resources/definitions.d.ts +15 -4
- package/dist/resources/definitions.d.ts.map +1 -1
- package/dist/resources/definitions.js +11 -2
- package/dist/resources/generate.d.ts +14 -3
- package/dist/resources/generate.d.ts.map +1 -1
- package/dist/resources/generate.js +10 -2
- package/dist/resources/generations.d.ts +3 -3
- package/dist/resources/generations.d.ts.map +1 -1
- package/dist/resources/generations.js +2 -0
- package/dist/resources/projects.d.ts +56 -20
- package/dist/resources/projects.d.ts.map +1 -1
- package/dist/resources/projects.js +40 -4
- package/dist/resources/targets.d.ts +84 -10
- package/dist/resources/targets.d.ts.map +1 -1
- package/dist/resources/targets.js +127 -2
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +55 -26
- package/dist/types.d.ts +602 -123
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +24 -0
- package/package.json +2 -1
- package/src/api-identity.ts +98 -0
- package/src/auth-profiles.ts +114 -0
- package/src/cli.ts +444 -332
- package/src/console-login-check.ts +88 -0
- package/src/console-login-contract.ts +65 -0
- package/src/core/http.ts +88 -19
- package/src/credential-storage.ts +183 -0
- package/src/docs.ts +138 -0
- package/src/errors.ts +26 -15
- package/src/index.ts +29 -4
- package/src/named-credentials.ts +74 -0
- package/src/oauth-login.ts +184 -0
- package/src/oauth-request.ts +90 -0
- package/src/oauth-session.ts +258 -0
- package/src/ops.ts +48 -31
- package/src/polling-login.ts +165 -0
- package/src/resources/account.ts +3 -0
- package/src/resources/api-keys.ts +5 -0
- package/src/resources/definition-revisions.ts +9 -0
- package/src/resources/definitions.ts +25 -0
- package/src/resources/generate.ts +23 -0
- package/src/resources/generations.ts +5 -0
- package/src/resources/projects.ts +95 -7
- package/src/resources/targets.ts +241 -0
- package/src/schemas.ts +55 -26
- package/src/types.ts +640 -123
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
2
|
+
import { oauthJsonRequest, oauthDeviceRequest, OAuthResponseError } from "./oauth-request.js";
|
|
3
|
+
|
|
4
|
+
export class LoginPollingError extends Error {
|
|
5
|
+
constructor(readonly code: "cancelled" | "expired" | "denied" | "invalid_response" | "request_failed") {
|
|
6
|
+
super({ cancelled: "Login was cancelled.", expired: "Login expired. Run login again and approve the new request.", denied: "Login was denied. Run login again if you want to retry.", invalid_response: "The login service returned an invalid response. Check its configuration.", request_failed: "The login request failed. Check the service and start a new login." }[code]);
|
|
7
|
+
this.name = "LoginPollingError";
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function loginEndpoint(value: string): URL {
|
|
12
|
+
try {
|
|
13
|
+
if (typeof value !== "string" || /[\x00-\x20\x7f]/.test(value)) throw new Error();
|
|
14
|
+
const url = new URL(value);
|
|
15
|
+
const local = ["localhost", "127.0.0.1", "[::1]"].includes(url.hostname);
|
|
16
|
+
if ((url.protocol !== "https:" && !(url.protocol === "http:" && local)) || url.username || url.password || url.hash) throw new Error();
|
|
17
|
+
return url;
|
|
18
|
+
} catch { throw new LoginPollingError("invalid_response"); }
|
|
19
|
+
}
|
|
20
|
+
function text(value: unknown, limit = 65_536): value is string {
|
|
21
|
+
return typeof value === "string" && value.trim().length > 0 && value.length <= limit && !/[\x00-\x1f\x7f]/.test(value);
|
|
22
|
+
}
|
|
23
|
+
function seconds(value: unknown): value is number {
|
|
24
|
+
return typeof value === "number" && Number.isFinite(value) && value > 0 && Number.isSafeInteger(Math.ceil(value * 1000));
|
|
25
|
+
}
|
|
26
|
+
function interval(value: unknown, fallback: number): number {
|
|
27
|
+
if (value === undefined) return fallback * 1000;
|
|
28
|
+
if (typeof value !== "number" || !Number.isFinite(value) || value < 0 || !Number.isSafeInteger(Math.ceil(value * 1000))) throw new LoginPollingError("invalid_response");
|
|
29
|
+
return Math.max(1, value) * 1000;
|
|
30
|
+
}
|
|
31
|
+
function lifetime(signal: AbortSignal | undefined, timeoutMs: number, maximum: number) {
|
|
32
|
+
if (!Number.isFinite(timeoutMs) || timeoutMs <= 0 || timeoutMs > maximum) throw new LoginPollingError("invalid_response");
|
|
33
|
+
const controller = new AbortController();
|
|
34
|
+
let expired = false;
|
|
35
|
+
const cancel = () => controller.abort();
|
|
36
|
+
const timer = setTimeout(() => { expired = true; controller.abort(); }, timeoutMs);
|
|
37
|
+
signal?.addEventListener("abort", cancel, { once: true });
|
|
38
|
+
if (signal?.aborted) cancel();
|
|
39
|
+
const check = () => { if (controller.signal.aborted) throw new LoginPollingError(expired ? "expired" : "cancelled"); };
|
|
40
|
+
return { signal: controller.signal, check, close() { clearTimeout(timer); signal?.removeEventListener("abort", cancel); } };
|
|
41
|
+
}
|
|
42
|
+
async function pause(ms: number, signal: AbortSignal): Promise<void> {
|
|
43
|
+
if (signal.aborted) throw new LoginPollingError("cancelled");
|
|
44
|
+
await new Promise<void>((resolve, reject) => {
|
|
45
|
+
const done = () => { clearTimeout(timer); signal.removeEventListener("abort", abort); resolve(); };
|
|
46
|
+
const abort = () => { clearTimeout(timer); signal.removeEventListener("abort", abort); reject(new LoginPollingError("cancelled")); };
|
|
47
|
+
const timer = setTimeout(done, Math.min(ms, 2_147_483_647));
|
|
48
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
const form = (params: Record<string, string>, signal: AbortSignal): RequestInit => ({ method: "POST", headers: { "Content-Type": "application/x-www-form-urlencoded", Accept: "application/json" }, body: new URLSearchParams(params), signal });
|
|
52
|
+
|
|
53
|
+
export interface DeviceLoginConfig {
|
|
54
|
+
clientId: string; issuer?: string | null; discoveryUrls: string[];
|
|
55
|
+
deviceUrl?: string | null; tokenUrl?: string | null;
|
|
56
|
+
scopes: string[]; audience?: string; resource?: string;
|
|
57
|
+
}
|
|
58
|
+
export interface DeviceLoginSession {
|
|
59
|
+
accessToken: string; refreshToken?: string; expiresAt?: number;
|
|
60
|
+
tokenUrl: string; issuer?: string; clientId: string; revocationUrl?: string; scopes?: string[];
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/** RFC 8628: pending and slow_down are the only responses that keep polling.
|
|
64
|
+
* All deadlines include response bodies; cancellation also interrupts waits. */
|
|
65
|
+
export async function oauthDeviceLogin(config: DeviceLoginConfig, interaction: {
|
|
66
|
+
authorize(value: { verificationUri: string; userCode: string; expiresIn: number }): void;
|
|
67
|
+
signal?: AbortSignal; timeoutMs?: number;
|
|
68
|
+
}): Promise<DeviceLoginSession> {
|
|
69
|
+
const flow = lifetime(interaction.signal, interaction.timeoutMs ?? 900_000, 900_000);
|
|
70
|
+
try {
|
|
71
|
+
flow.check();
|
|
72
|
+
if (!text(config.clientId)) throw new LoginPollingError("invalid_response");
|
|
73
|
+
if (config.issuer && loginEndpoint(config.issuer).search) throw new LoginPollingError("invalid_response");
|
|
74
|
+
let deviceUrl = config.deviceUrl ? loginEndpoint(config.deviceUrl).href : undefined;
|
|
75
|
+
let tokenUrl = config.tokenUrl ? loginEndpoint(config.tokenUrl).href : undefined;
|
|
76
|
+
let revocationUrl: string | undefined;
|
|
77
|
+
for (const url of config.discoveryUrls) {
|
|
78
|
+
if (deviceUrl && tokenUrl) break;
|
|
79
|
+
const response = await oauthJsonRequest(loginEndpoint(url), { headers: { Accept: "application/json" }, signal: flow.signal }, 10_000);
|
|
80
|
+
if (response.status !== 200) continue;
|
|
81
|
+
const data = response.data!;
|
|
82
|
+
if (config.issuer && data.issuer !== config.issuer) throw new LoginPollingError("invalid_response");
|
|
83
|
+
if (!deviceUrl && typeof data.device_authorization_endpoint === "string") deviceUrl = loginEndpoint(data.device_authorization_endpoint).href;
|
|
84
|
+
if (!tokenUrl && typeof data.token_endpoint === "string") tokenUrl = loginEndpoint(data.token_endpoint).href;
|
|
85
|
+
if (data.revocation_endpoint !== undefined) revocationUrl = loginEndpoint(data.revocation_endpoint as string).href;
|
|
86
|
+
}
|
|
87
|
+
if (!deviceUrl || !tokenUrl) throw new LoginPollingError("invalid_response");
|
|
88
|
+
const params = { ...(config.audience ? { audience: config.audience } : {}), ...(config.resource ? { resource: config.resource } : {}) };
|
|
89
|
+
const start = await oauthJsonRequest(deviceUrl, form({ client_id: config.clientId, ...(config.scopes.length ? { scope: config.scopes.join(" ") } : {}), ...params }, flow.signal));
|
|
90
|
+
const data = start.data;
|
|
91
|
+
if (start.status !== 200) throw new LoginPollingError("request_failed");
|
|
92
|
+
if (!data || !text(data.device_code) || !text(data.user_code, 512) || !text(data.verification_uri, 8192) || !seconds(data.expires_in)) throw new LoginPollingError("invalid_response");
|
|
93
|
+
loginEndpoint(data.verification_uri);
|
|
94
|
+
const verificationUri = loginEndpoint((data.verification_uri_complete ?? data.verification_uri) as string).href;
|
|
95
|
+
let intervalMs = interval(data.interval, 5);
|
|
96
|
+
const expiresIn = Math.min(data.expires_in, 900), deadline = Date.now() + expiresIn * 1000;
|
|
97
|
+
interaction.authorize({ verificationUri, userCode: data.user_code, expiresIn });
|
|
98
|
+
while (true) {
|
|
99
|
+
await pause(Math.min(intervalMs, Math.max(0, deadline - Date.now())), flow.signal);
|
|
100
|
+
flow.check();
|
|
101
|
+
if (Date.now() >= deadline) throw new LoginPollingError("expired");
|
|
102
|
+
let response: Awaited<ReturnType<typeof oauthDeviceRequest>>;
|
|
103
|
+
try { response = await oauthDeviceRequest(tokenUrl, form({ ...params, grant_type: "urn:ietf:params:oauth:grant-type:device_code", device_code: data.device_code, client_id: config.clientId }, flow.signal), Math.min(30_000, deadline - Date.now())); }
|
|
104
|
+
catch (error) {
|
|
105
|
+
flow.check();
|
|
106
|
+
if (error instanceof OAuthResponseError && error.code === "timed_out") { intervalMs *= 2; continue; }
|
|
107
|
+
throw error;
|
|
108
|
+
}
|
|
109
|
+
flow.check();
|
|
110
|
+
if (Date.now() >= deadline) throw new LoginPollingError("expired");
|
|
111
|
+
if (response.status === 400 && response.error === "authorization_pending") continue;
|
|
112
|
+
if (response.status === 400 && response.error === "slow_down") { intervalMs += 5000; continue; }
|
|
113
|
+
if (response.status === 400 && response.error === "access_denied") throw new LoginPollingError("denied");
|
|
114
|
+
if (response.status === 400 && response.error === "expired_token") throw new LoginPollingError("expired");
|
|
115
|
+
if (response.status !== 200) throw new LoginPollingError("request_failed");
|
|
116
|
+
const token = response.data!;
|
|
117
|
+
if (!text(token.access_token) || typeof token.token_type !== "string" || token.token_type.toLowerCase() !== "bearer" || token.error !== undefined || token.refresh_token !== undefined && !text(token.refresh_token) || token.expires_in !== undefined && !seconds(token.expires_in) || token.scope !== undefined && typeof token.scope !== "string") throw new LoginPollingError("invalid_response");
|
|
118
|
+
return { accessToken: token.access_token, ...(typeof token.refresh_token === "string" ? { refreshToken: token.refresh_token } : {}), ...(typeof token.expires_in === "number" ? { expiresAt: Date.now() + token.expires_in * 1000 } : {}), clientId: config.clientId, tokenUrl, ...(config.issuer ? { issuer: config.issuer } : {}), ...(revocationUrl ? { revocationUrl } : {}), ...(typeof token.scope === "string" ? { scopes: token.scope.split(/\s+/).filter(Boolean) } : {}) };
|
|
119
|
+
}
|
|
120
|
+
} catch (error) { flow.check(); throw error; }
|
|
121
|
+
finally { flow.close(); }
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface ApprovedCredential { api_key: string; key_name: string; org_id?: string; revocationUrl: string }
|
|
125
|
+
|
|
126
|
+
/** This is the owner's custom approval contract, not an OAuth grant. A failed
|
|
127
|
+
* poll is not replayed: its one-use credential may already have been consumed. */
|
|
128
|
+
export async function customBrowserApproval(config: { authUrl: string; name: string; source: "agent" | "cli" }, interaction: {
|
|
129
|
+
authorize(value: { verificationUrl: string; expiresIn: number }): void;
|
|
130
|
+
signal?: AbortSignal; timeoutMs?: number;
|
|
131
|
+
}): Promise<ApprovedCredential> {
|
|
132
|
+
const flow = lifetime(interaction.signal, interaction.timeoutMs ?? 600_000, 600_000);
|
|
133
|
+
try {
|
|
134
|
+
flow.check();
|
|
135
|
+
const base = loginEndpoint(config.authUrl);
|
|
136
|
+
if (base.search) throw new LoginPollingError("invalid_response");
|
|
137
|
+
const url = base.href.replace(/\/$/, "");
|
|
138
|
+
const verifier = randomBytes(32).toString("base64url"), challenge = createHash("sha256").update(verifier).digest("base64url");
|
|
139
|
+
const post = (body: unknown): RequestInit => ({ method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json" }, body: JSON.stringify(body), signal: flow.signal });
|
|
140
|
+
const response = await oauthJsonRequest(url + "/start", post({ code_challenge: challenge, name: config.name, source: config.source }), 15_000);
|
|
141
|
+
if (response.status !== 200) throw new LoginPollingError("request_failed");
|
|
142
|
+
const start = response.data!;
|
|
143
|
+
if (!text(start.session) || !text(start.verification_url, 8192) || start.expires_in !== undefined && !seconds(start.expires_in)) throw new LoginPollingError("invalid_response");
|
|
144
|
+
const verificationUrl = loginEndpoint(start.verification_url).href;
|
|
145
|
+
const expiresIn = Math.min(typeof start.expires_in === "number" ? start.expires_in : 600, 600);
|
|
146
|
+
const intervalMs = interval(start.interval, 3), deadline = Date.now() + expiresIn * 1000;
|
|
147
|
+
interaction.authorize({ verificationUrl, expiresIn });
|
|
148
|
+
while (true) {
|
|
149
|
+
await pause(Math.min(intervalMs, Math.max(0, deadline - Date.now())), flow.signal);
|
|
150
|
+
flow.check();
|
|
151
|
+
if (Date.now() >= deadline) throw new LoginPollingError("expired");
|
|
152
|
+
const result = await oauthJsonRequest(url + "/status", post({ session: start.session, code_verifier: verifier }), Math.min(15_000, deadline - Date.now()));
|
|
153
|
+
flow.check();
|
|
154
|
+
if (Date.now() >= deadline) throw new LoginPollingError("expired");
|
|
155
|
+
if (result.status !== 200) throw new LoginPollingError("request_failed");
|
|
156
|
+
const poll = result.data!;
|
|
157
|
+
if (poll.status === "pending") continue;
|
|
158
|
+
if (poll.status === "denied") throw new LoginPollingError("denied");
|
|
159
|
+
if (poll.status === "expired") throw new LoginPollingError("expired");
|
|
160
|
+
if (poll.status !== "complete" || !text(poll.api_key) || poll.key_name !== undefined && !text(poll.key_name, 1024) || poll.org_id !== undefined && !text(poll.org_id, 1024)) throw new LoginPollingError("invalid_response");
|
|
161
|
+
return { api_key: poll.api_key, key_name: typeof poll.key_name === "string" ? poll.key_name : config.name, ...(typeof poll.org_id === "string" ? { org_id: poll.org_id } : {}), revocationUrl: url + "/revoke" };
|
|
162
|
+
}
|
|
163
|
+
} catch (error) { flow.check(); throw error; }
|
|
164
|
+
finally { flow.close(); }
|
|
165
|
+
}
|
package/src/resources/account.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import { HttpCore, type ApiResult, type RequestOptions } from "../core/http.js";
|
|
5
5
|
import {
|
|
6
|
+
ResponseParseError,
|
|
6
7
|
TransportError,
|
|
7
8
|
UnexpectedApiError,
|
|
8
9
|
ValidationError,
|
|
@@ -25,6 +26,7 @@ export class AccountResource {
|
|
|
25
26
|
return this._core.request<AccountRead, AccountRetrieveError>({
|
|
26
27
|
method: "GET",
|
|
27
28
|
path: "/me",
|
|
29
|
+
security: [{"apiKey":[]}],
|
|
28
30
|
errors: { "401": UnauthorizedError, "403": ForbiddenError, "429": RateLimitedError },
|
|
29
31
|
idempotent: true,
|
|
30
32
|
schemaKey: "account.retrieve",
|
|
@@ -39,5 +41,6 @@ export type AccountRetrieveError =
|
|
|
39
41
|
| ForbiddenError
|
|
40
42
|
| RateLimitedError
|
|
41
43
|
| UnexpectedApiError
|
|
44
|
+
| ResponseParseError
|
|
42
45
|
| TransportError
|
|
43
46
|
| ValidationError;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { HttpCore, type ApiResult, type RequestOptions } from "../core/http.js";
|
|
5
5
|
import { paginate, PagePromise } from "../core/pagination.js";
|
|
6
6
|
import {
|
|
7
|
+
ResponseParseError,
|
|
7
8
|
TransportError,
|
|
8
9
|
UnexpectedApiError,
|
|
9
10
|
ValidationError,
|
|
@@ -37,6 +38,7 @@ export class ApiKeysResource {
|
|
|
37
38
|
return paginate<ApiKeyRead, ApiKeysListError>(this._core, {
|
|
38
39
|
method: "GET",
|
|
39
40
|
path: "/api_keys",
|
|
41
|
+
security: [{"apiKey":[]}],
|
|
40
42
|
query: {
|
|
41
43
|
limit: params?.limit,
|
|
42
44
|
cursor: params?.cursor,
|
|
@@ -76,6 +78,7 @@ export class ApiKeysResource {
|
|
|
76
78
|
return this._core.request<ApiKeyResponseRead, ApiKeysRevokeError>({
|
|
77
79
|
method: "DELETE",
|
|
78
80
|
path: `/api_keys/${encodeURIComponent(String(apiKeyId))}`,
|
|
81
|
+
security: [{"apiKey":[]}],
|
|
79
82
|
errors: {
|
|
80
83
|
"401": UnauthorizedError,
|
|
81
84
|
"403": ForbiddenError,
|
|
@@ -106,6 +109,7 @@ export type ApiKeysListError =
|
|
|
106
109
|
| ForbiddenError
|
|
107
110
|
| RateLimitedError
|
|
108
111
|
| UnexpectedApiError
|
|
112
|
+
| ResponseParseError
|
|
109
113
|
| TransportError
|
|
110
114
|
| ValidationError;
|
|
111
115
|
|
|
@@ -116,5 +120,6 @@ export type ApiKeysRevokeError =
|
|
|
116
120
|
| NotFoundError
|
|
117
121
|
| RateLimitedError
|
|
118
122
|
| UnexpectedApiError
|
|
123
|
+
| ResponseParseError
|
|
119
124
|
| TransportError
|
|
120
125
|
| ValidationError;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { HttpCore, type ApiResult, type RequestOptions } from "../core/http.js";
|
|
5
5
|
import { paginate, PagePromise } from "../core/pagination.js";
|
|
6
6
|
import {
|
|
7
|
+
ResponseParseError,
|
|
7
8
|
TransportError,
|
|
8
9
|
UnexpectedApiError,
|
|
9
10
|
ValidationError,
|
|
@@ -45,6 +46,7 @@ export class DefinitionRevisionsResource {
|
|
|
45
46
|
return paginate<DefinitionRevisionRead, DefinitionRevisionsListError>(this._core, {
|
|
46
47
|
method: "GET",
|
|
47
48
|
path: `/definitions/${encodeURIComponent(String(definitionId))}/revisions`,
|
|
49
|
+
security: [{"apiKey":[]}],
|
|
48
50
|
query: {
|
|
49
51
|
limit: params?.limit,
|
|
50
52
|
cursor: params?.cursor,
|
|
@@ -83,6 +85,7 @@ export class DefinitionRevisionsResource {
|
|
|
83
85
|
return this._core.request<DefinitionRevisionResponseRead, DefinitionRevisionsRetrieveError>({
|
|
84
86
|
method: "GET",
|
|
85
87
|
path: `/definition_revisions/${encodeURIComponent(String(definitionRevisionId))}`,
|
|
88
|
+
security: [{"apiKey":[]}],
|
|
86
89
|
errors: {
|
|
87
90
|
"401": UnauthorizedError,
|
|
88
91
|
"403": ForbiddenError,
|
|
@@ -109,6 +112,7 @@ export class DefinitionRevisionsResource {
|
|
|
109
112
|
return this._core.request<string, DefinitionRevisionsRetrieveContentError>({
|
|
110
113
|
method: "GET",
|
|
111
114
|
path: `/definition_revisions/${encodeURIComponent(String(definitionRevisionId))}/content`,
|
|
115
|
+
security: [{"apiKey":[]}],
|
|
112
116
|
errors: {
|
|
113
117
|
"401": UnauthorizedError,
|
|
114
118
|
"403": ForbiddenError,
|
|
@@ -133,6 +137,7 @@ export class DefinitionRevisionsResource {
|
|
|
133
137
|
return this._core.request<string, DefinitionRevisionsRetrieveDocumentContentError>({
|
|
134
138
|
method: "GET",
|
|
135
139
|
path: `/definition_revisions/${encodeURIComponent(String(definitionRevisionId))}/documents/${encodeURIComponent(String(documentId))}/content`,
|
|
140
|
+
security: [{"apiKey":[]}],
|
|
136
141
|
errors: {
|
|
137
142
|
"401": UnauthorizedError,
|
|
138
143
|
"403": ForbiddenError,
|
|
@@ -164,6 +169,7 @@ export type DefinitionRevisionsListError =
|
|
|
164
169
|
| NotFoundError
|
|
165
170
|
| RateLimitedError
|
|
166
171
|
| UnexpectedApiError
|
|
172
|
+
| ResponseParseError
|
|
167
173
|
| TransportError
|
|
168
174
|
| ValidationError;
|
|
169
175
|
|
|
@@ -174,6 +180,7 @@ export type DefinitionRevisionsRetrieveError =
|
|
|
174
180
|
| NotFoundError
|
|
175
181
|
| RateLimitedError
|
|
176
182
|
| UnexpectedApiError
|
|
183
|
+
| ResponseParseError
|
|
177
184
|
| TransportError
|
|
178
185
|
| ValidationError;
|
|
179
186
|
|
|
@@ -184,6 +191,7 @@ export type DefinitionRevisionsRetrieveContentError =
|
|
|
184
191
|
| NotFoundError
|
|
185
192
|
| RateLimitedError
|
|
186
193
|
| UnexpectedApiError
|
|
194
|
+
| ResponseParseError
|
|
187
195
|
| TransportError
|
|
188
196
|
| ValidationError;
|
|
189
197
|
|
|
@@ -194,5 +202,6 @@ export type DefinitionRevisionsRetrieveDocumentContentError =
|
|
|
194
202
|
| NotFoundError
|
|
195
203
|
| RateLimitedError
|
|
196
204
|
| UnexpectedApiError
|
|
205
|
+
| ResponseParseError
|
|
197
206
|
| TransportError
|
|
198
207
|
| ValidationError;
|
|
@@ -3,10 +3,12 @@
|
|
|
3
3
|
|
|
4
4
|
import { HttpCore, type ApiResult, type RequestOptions } from "../core/http.js";
|
|
5
5
|
import {
|
|
6
|
+
ResponseParseError,
|
|
6
7
|
TransportError,
|
|
7
8
|
UnexpectedApiError,
|
|
8
9
|
ValidationError,
|
|
9
10
|
BadRequestError,
|
|
11
|
+
ConflictError,
|
|
10
12
|
ForbiddenError,
|
|
11
13
|
NotFoundError,
|
|
12
14
|
RateLimitedError,
|
|
@@ -33,6 +35,7 @@ export class DefinitionsResource {
|
|
|
33
35
|
return this._core.request<DefinitionRead, DefinitionsRetrieveError>({
|
|
34
36
|
method: "GET",
|
|
35
37
|
path: `/definitions/${encodeURIComponent(String(definitionId))}`,
|
|
38
|
+
security: [{"apiKey":[]}],
|
|
36
39
|
errors: {
|
|
37
40
|
"401": UnauthorizedError,
|
|
38
41
|
"403": ForbiddenError,
|
|
@@ -49,25 +52,34 @@ export class DefinitionsResource {
|
|
|
49
52
|
* Update and resolve a Definition
|
|
50
53
|
*
|
|
51
54
|
* Resolves the complete document graph and records a new immutable revision before saving.
|
|
55
|
+
*
|
|
56
|
+
* A `Idempotency-Key` UUID is generated per call (stable across retries) unless you pass one.
|
|
52
57
|
* `PATCH /definitions/{definition_id}`
|
|
53
58
|
*/
|
|
54
59
|
async update(
|
|
55
60
|
definitionId: DefinitionId,
|
|
56
61
|
body: DefinitionUpdateRequest,
|
|
62
|
+
params?: DefinitionsUpdateParams,
|
|
57
63
|
options?: RequestOptions,
|
|
58
64
|
): Promise<ApiResult<DefinitionRead, DefinitionsUpdateError>> {
|
|
59
65
|
return this._core.request<DefinitionRead, DefinitionsUpdateError>({
|
|
60
66
|
method: "PATCH",
|
|
61
67
|
path: `/definitions/${encodeURIComponent(String(definitionId))}`,
|
|
68
|
+
security: [{"apiKey":[]}],
|
|
69
|
+
headers: {
|
|
70
|
+
"Idempotency-Key": params?.idempotencyKey === undefined ? undefined : String(params?.idempotencyKey),
|
|
71
|
+
},
|
|
62
72
|
body,
|
|
63
73
|
errors: {
|
|
64
74
|
"400": BadRequestError,
|
|
65
75
|
"401": UnauthorizedError,
|
|
66
76
|
"403": ForbiddenError,
|
|
67
77
|
"404": NotFoundError,
|
|
78
|
+
"409": ConflictError,
|
|
68
79
|
"422": UnprocessableEntityError,
|
|
69
80
|
"429": RateLimitedError,
|
|
70
81
|
},
|
|
82
|
+
idempotencyKey: "Idempotency-Key",
|
|
71
83
|
schemaKey: "definitions.update",
|
|
72
84
|
options,
|
|
73
85
|
});
|
|
@@ -81,17 +93,30 @@ export type DefinitionsRetrieveError =
|
|
|
81
93
|
| NotFoundError
|
|
82
94
|
| RateLimitedError
|
|
83
95
|
| UnexpectedApiError
|
|
96
|
+
| ResponseParseError
|
|
84
97
|
| TransportError
|
|
85
98
|
| ValidationError;
|
|
86
99
|
|
|
100
|
+
export interface DefinitionsUpdateParams {
|
|
101
|
+
/**
|
|
102
|
+
* Identifies one logical write for 24 hours. The key is scoped to the authenticated account and
|
|
103
|
+
* operation; account-less generation uses a hashed network identity. Retrying the same method,
|
|
104
|
+
* path, query, and JSON body replays the original response. Reusing the key with changed intent
|
|
105
|
+
* returns 409. After expiry the key starts a new write.
|
|
106
|
+
*/
|
|
107
|
+
idempotencyKey?: string;
|
|
108
|
+
}
|
|
109
|
+
|
|
87
110
|
/** Every error `update` can produce, as a discriminated union. */
|
|
88
111
|
export type DefinitionsUpdateError =
|
|
89
112
|
| BadRequestError
|
|
90
113
|
| UnauthorizedError
|
|
91
114
|
| ForbiddenError
|
|
92
115
|
| NotFoundError
|
|
116
|
+
| ConflictError
|
|
93
117
|
| UnprocessableEntityError
|
|
94
118
|
| RateLimitedError
|
|
95
119
|
| UnexpectedApiError
|
|
120
|
+
| ResponseParseError
|
|
96
121
|
| TransportError
|
|
97
122
|
| ValidationError;
|
|
@@ -3,11 +3,13 @@
|
|
|
3
3
|
|
|
4
4
|
import { HttpCore, type ApiResult, type RequestOptions } from "../core/http.js";
|
|
5
5
|
import {
|
|
6
|
+
ResponseParseError,
|
|
6
7
|
TransportError,
|
|
7
8
|
UnexpectedApiError,
|
|
8
9
|
ValidationError,
|
|
9
10
|
ApiResponseError,
|
|
10
11
|
BadRequestError,
|
|
12
|
+
ConflictError,
|
|
11
13
|
ForbiddenError,
|
|
12
14
|
PayloadTooLargeError,
|
|
13
15
|
RateLimitedError,
|
|
@@ -30,40 +32,61 @@ export class GenerateResource {
|
|
|
30
32
|
* the first 25 operations and
|
|
31
33
|
* paid plans generate the complete Definition. A present but invalid key is a
|
|
32
34
|
* 401, not a downgrade to anonymous.
|
|
35
|
+
*
|
|
36
|
+
* A `Idempotency-Key` UUID is generated per call (stable across retries) unless you pass one.
|
|
33
37
|
* `POST /generate`
|
|
34
38
|
*/
|
|
35
39
|
async run(
|
|
36
40
|
body: GenerateRequest,
|
|
41
|
+
params?: GenerateRunParams,
|
|
37
42
|
options?: RequestOptions,
|
|
38
43
|
): Promise<ApiResult<GenerationResultRead, GenerateRunError>> {
|
|
39
44
|
return this._core.request<GenerationResultRead, GenerateRunError>({
|
|
40
45
|
method: "POST",
|
|
41
46
|
path: "/generate",
|
|
47
|
+
security: [{},{"apiKey":[]}],
|
|
48
|
+
headers: {
|
|
49
|
+
"Idempotency-Key": params?.idempotencyKey === undefined ? undefined : String(params?.idempotencyKey),
|
|
50
|
+
},
|
|
42
51
|
body,
|
|
43
52
|
errors: {
|
|
44
53
|
"400": BadRequestError,
|
|
45
54
|
"401": UnauthorizedError,
|
|
46
55
|
"403": ForbiddenError,
|
|
56
|
+
"409": ConflictError,
|
|
47
57
|
"413": PayloadTooLargeError,
|
|
48
58
|
"422": UnprocessableEntityError,
|
|
49
59
|
"429": RateLimitedError,
|
|
50
60
|
default: ApiResponseError,
|
|
51
61
|
},
|
|
62
|
+
idempotencyKey: "Idempotency-Key",
|
|
52
63
|
schemaKey: "generate.run",
|
|
53
64
|
options,
|
|
54
65
|
});
|
|
55
66
|
}
|
|
56
67
|
}
|
|
57
68
|
|
|
69
|
+
export interface GenerateRunParams {
|
|
70
|
+
/**
|
|
71
|
+
* Identifies one logical write for 24 hours. The key is scoped to the authenticated account and
|
|
72
|
+
* operation; account-less generation uses a hashed network identity. Retrying the same method,
|
|
73
|
+
* path, query, and JSON body replays the original response. Reusing the key with changed intent
|
|
74
|
+
* returns 409. After expiry the key starts a new write.
|
|
75
|
+
*/
|
|
76
|
+
idempotencyKey?: string;
|
|
77
|
+
}
|
|
78
|
+
|
|
58
79
|
/** Every error `run` can produce, as a discriminated union. */
|
|
59
80
|
export type GenerateRunError =
|
|
60
81
|
| BadRequestError
|
|
61
82
|
| UnauthorizedError
|
|
62
83
|
| ForbiddenError
|
|
84
|
+
| ConflictError
|
|
63
85
|
| PayloadTooLargeError
|
|
64
86
|
| UnprocessableEntityError
|
|
65
87
|
| RateLimitedError
|
|
66
88
|
| ApiResponseError
|
|
67
89
|
| UnexpectedApiError
|
|
90
|
+
| ResponseParseError
|
|
68
91
|
| TransportError
|
|
69
92
|
| ValidationError;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import { HttpCore, type ApiResult, type RequestOptions } from "../core/http.js";
|
|
5
5
|
import {
|
|
6
|
+
ResponseParseError,
|
|
6
7
|
TransportError,
|
|
7
8
|
UnexpectedApiError,
|
|
8
9
|
ValidationError,
|
|
@@ -29,6 +30,7 @@ export class GenerationsResource {
|
|
|
29
30
|
return this._core.request<GenerationResponseRead, GenerationsRetrieveError>({
|
|
30
31
|
method: "GET",
|
|
31
32
|
path: `/generations/${encodeURIComponent(String(generationId))}`,
|
|
33
|
+
security: [{"apiKey":[]}],
|
|
32
34
|
errors: {
|
|
33
35
|
"401": UnauthorizedError,
|
|
34
36
|
"403": ForbiddenError,
|
|
@@ -56,6 +58,7 @@ export class GenerationsResource {
|
|
|
56
58
|
return this._core.request<string, GenerationsRetrieveFileError>({
|
|
57
59
|
method: "GET",
|
|
58
60
|
path: `/generations/${encodeURIComponent(String(generationId))}/file`,
|
|
61
|
+
security: [{"apiKey":[]}],
|
|
59
62
|
query: {
|
|
60
63
|
path: params.path,
|
|
61
64
|
},
|
|
@@ -80,6 +83,7 @@ export type GenerationsRetrieveError =
|
|
|
80
83
|
| NotFoundError
|
|
81
84
|
| RateLimitedError
|
|
82
85
|
| UnexpectedApiError
|
|
86
|
+
| ResponseParseError
|
|
83
87
|
| TransportError
|
|
84
88
|
| ValidationError;
|
|
85
89
|
|
|
@@ -96,5 +100,6 @@ export type GenerationsRetrieveFileError =
|
|
|
96
100
|
| NotFoundError
|
|
97
101
|
| RateLimitedError
|
|
98
102
|
| UnexpectedApiError
|
|
103
|
+
| ResponseParseError
|
|
99
104
|
| TransportError
|
|
100
105
|
| ValidationError;
|