@typeship-ax/cli 0.10.0 → 0.21.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 +10 -5
- package/README.md +5 -5
- package/api.json +9773 -4501
- package/api.md +501 -271
- package/dist/api-identity.d.ts.map +1 -1
- package/dist/api-identity.js +6 -1
- package/dist/cli-agent.d.ts +5 -5
- package/dist/cli-agent.d.ts.map +1 -1
- package/dist/cli-agent.js +14 -10
- package/dist/cli.js +158 -82
- package/dist/core/http.d.ts +29 -16
- package/dist/core/http.d.ts.map +1 -1
- package/dist/core/http.js +108 -25
- package/dist/core/pagination.d.ts +8 -8
- package/dist/core/pagination.d.ts.map +1 -1
- package/dist/core/pagination.js +7 -16
- package/dist/errors.d.ts +20 -13
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +29 -20
- package/dist/index.d.ts +37 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +42 -18
- package/dist/ops.d.ts +5 -1
- package/dist/ops.d.ts.map +1 -1
- package/dist/ops.js +42 -35
- package/dist/polling-login.d.ts.map +1 -1
- package/dist/polling-login.js +11 -1
- package/dist/resources/api-keys.d.ts +44 -18
- package/dist/resources/api-keys.d.ts.map +1 -1
- package/dist/resources/api-keys.js +46 -14
- package/dist/resources/deliveries.d.ts +46 -0
- package/dist/resources/deliveries.d.ts.map +1 -0
- package/dist/resources/deliveries.js +70 -0
- package/dist/resources/drafts.d.ts +155 -0
- package/dist/resources/drafts.d.ts.map +1 -0
- package/dist/resources/drafts.js +230 -0
- package/dist/resources/files.d.ts +23 -0
- package/dist/resources/files.d.ts.map +1 -0
- package/dist/resources/files.js +38 -0
- package/dist/resources/generate.d.ts +49 -20
- package/dist/resources/generate.d.ts.map +1 -1
- package/dist/resources/generate.js +56 -14
- package/dist/resources/generations.d.ts +70 -18
- package/dist/resources/generations.d.ts.map +1 -1
- package/dist/resources/generations.js +84 -16
- package/dist/resources/organization.d.ts +18 -0
- package/dist/resources/organization.d.ts.map +1 -0
- package/dist/resources/organization.js +32 -0
- package/dist/resources/projects.d.ts +87 -124
- package/dist/resources/projects.d.ts.map +1 -1
- package/dist/resources/projects.js +70 -173
- package/dist/resources/publications.d.ts +46 -0
- package/dist/resources/publications.d.ts.map +1 -0
- package/dist/resources/publications.js +70 -0
- package/dist/resources/releases.d.ts +66 -0
- package/dist/resources/releases.d.ts.map +1 -0
- package/dist/resources/releases.js +101 -0
- package/dist/resources/spec-revisions.d.ts +85 -0
- package/dist/resources/spec-revisions.d.ts.map +1 -0
- package/dist/resources/spec-revisions.js +116 -0
- package/dist/resources/specs.d.ts +72 -0
- package/dist/resources/specs.d.ts.map +1 -0
- package/dist/resources/specs.js +107 -0
- package/dist/resources/targets.d.ts +85 -105
- package/dist/resources/targets.d.ts.map +1 -1
- package/dist/resources/targets.js +70 -163
- package/dist/schemas.d.ts +1 -0
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +194 -139
- package/dist/types.d.ts +2626 -1141
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +90 -11
- package/package.json +3 -3
- package/src/api-identity.ts +6 -2
- package/src/cli-agent.ts +17 -13
- package/src/cli.ts +145 -77
- package/src/core/http.ts +106 -30
- package/src/core/pagination.ts +13 -23
- package/src/errors.ts +30 -20
- package/src/index.ts +46 -24
- package/src/ops.ts +47 -36
- package/src/polling-login.ts +10 -1
- package/src/resources/api-keys.ts +87 -19
- package/src/resources/deliveries.ts +139 -0
- package/src/resources/drafts.ts +422 -0
- package/src/resources/files.ts +68 -0
- package/src/resources/generate.ts +81 -19
- package/src/resources/generations.ts +167 -29
- package/src/resources/organization.ts +53 -0
- package/src/resources/projects.ts +129 -322
- package/src/resources/publications.ts +139 -0
- package/src/resources/releases.ts +199 -0
- package/src/resources/spec-revisions.ts +237 -0
- package/src/resources/specs.ts +200 -0
- package/src/resources/targets.ts +135 -304
- package/src/schemas.ts +195 -140
- package/src/types.ts +2793 -1177
- package/dist/resources/account.d.ts +0 -18
- package/dist/resources/account.d.ts.map +0 -1
- package/dist/resources/account.js +0 -27
- package/dist/resources/definition-revisions.d.ts +0 -58
- package/dist/resources/definition-revisions.d.ts.map +0 -1
- package/dist/resources/definition-revisions.js +0 -114
- package/dist/resources/definitions.d.ts +0 -35
- package/dist/resources/definitions.d.ts.map +0 -1
- package/dist/resources/definitions.js +0 -60
- package/src/resources/account.ts +0 -46
- package/src/resources/definition-revisions.ts +0 -207
- package/src/resources/definitions.ts +0 -122
package/dist/cli.js
CHANGED
|
@@ -20,6 +20,8 @@ import { homedir, hostname } from "node:os";
|
|
|
20
20
|
import { basename, join } from "node:path";
|
|
21
21
|
import { fileURLToPath } from "node:url";
|
|
22
22
|
import { TypeshipClient, formatDebugEvent } from "./index.js";
|
|
23
|
+
import { asApiResult, validateAgainstSchema, ValidationError } from "./core/http.js";
|
|
24
|
+
import { SCHEMAS, DEFS } from "./schemas.js";
|
|
23
25
|
import { GLOBALS, OMITTED_OPS, OPS, buildArgs, findOp, missingRequired } from "./ops.js";
|
|
24
26
|
import { MCP_CLIENTS, agentGuide, agentBlock, agentInstructionsFile, agentMode, bundleProperty, claimProperty, classifyApiError, collectionProperty, detectHarness, envelope, exitCodeFor, findMcpClient, installSkills, mcpConfigured, pendingClaims, recordClaim, summarizeDoctor, upsertAgentBlock, writeBundle, writeMcpConfig, } from "./cli-agent.js";
|
|
25
27
|
import { relativeDate } from "./dates.js";
|
|
@@ -33,17 +35,17 @@ const BASIC = null;
|
|
|
33
35
|
const EXCLUDED_OPS = 0;
|
|
34
36
|
/** Generated CLI operations that are intentionally unavailable to MCP. */
|
|
35
37
|
const MCP_EXCLUDED_OPS = 0;
|
|
36
|
-
const VERSION = "0.
|
|
38
|
+
const VERSION = "0.21.0";
|
|
37
39
|
const API_VERSION = "1.0.0";
|
|
38
40
|
const SPEC_FORMAT = "openapi";
|
|
39
41
|
const IDENTITY_POLICY = {};
|
|
40
42
|
let LOGIN_IDENTITY;
|
|
41
|
-
const WHOAMI =
|
|
43
|
+
const WHOAMI = null;
|
|
42
44
|
const ENVIRONMENTS = {};
|
|
43
45
|
const HAS_MCP = false;
|
|
44
46
|
const PKG_NAME = "@typeship-ax/cli";
|
|
45
47
|
const UPDATE_NOTICE = false;
|
|
46
|
-
const API_DESCRIPTION = "Resolve an OpenAPI or GraphQL
|
|
48
|
+
const API_DESCRIPTION = "Resolve an OpenAPI or GraphQL Spec, diagnose it, and keep every\nselected CLI, MCP, and SDK Target current.\n\nEvery operation but one requires a bearer credential: an organization\nAPI key from the console, or an OAuth access token carrying the operation's\nread, generate, or write capability and the organization selected during\nconsent. OAuth grants cannot switch organizations after consent. A browser\nsession is not a credential for this API. The exception is POST /generate,\nwhich works anonymously with the free plan's limits.\n\nExamples use Parcel, a fictional delivery service. Replace its domains,\nrepository names, and resource identifiers with your own. The hosted\npetstore Spec is a runnable sample.\n";
|
|
47
49
|
const DOCS_URL_DEFAULT = "https://typeship.dev";
|
|
48
50
|
const DOCS_INDEX_URL_DEFAULT = null;
|
|
49
51
|
const RELAY = null;
|
|
@@ -136,7 +138,8 @@ function parseArgv(argv) {
|
|
|
136
138
|
}
|
|
137
139
|
else if (isBooleanFlag(arg.slice(2), positionals)) {
|
|
138
140
|
const next = argv[i + 1];
|
|
139
|
-
|
|
141
|
+
const nullable = positionals.length >= 2 && findOp(positionals[0], positionals[1])?.params.some((p) => p.flag === arg.slice(2) && p.nullable);
|
|
142
|
+
if (next === "true" || next === "false" || (next === "null" && nullable)) {
|
|
140
143
|
setFlag(arg.slice(2), next);
|
|
141
144
|
i++;
|
|
142
145
|
}
|
|
@@ -215,33 +218,32 @@ function out(value) {
|
|
|
215
218
|
/** --fields a,b.c: the dotted paths to keep in API results (null = everything). Set in main(). */
|
|
216
219
|
let FIELDS = null;
|
|
217
220
|
/** Keep only FIELDS of a result: arrays item by item, objects by dotted path; scalars untouched. */
|
|
218
|
-
function project(value) {
|
|
219
|
-
if (
|
|
221
|
+
function project(value, paths = FIELDS) {
|
|
222
|
+
if (paths === null)
|
|
220
223
|
return value;
|
|
221
224
|
if (Array.isArray(value))
|
|
222
|
-
return value.map(project);
|
|
225
|
+
return value.map((item) => project(item, paths));
|
|
223
226
|
if (value === null || typeof value !== "object")
|
|
224
227
|
return value;
|
|
228
|
+
const groups = new Map();
|
|
229
|
+
for (const [key, ...rest] of paths) {
|
|
230
|
+
if (key === undefined)
|
|
231
|
+
continue;
|
|
232
|
+
const group = groups.get(key);
|
|
233
|
+
if (group)
|
|
234
|
+
group.push(rest);
|
|
235
|
+
else
|
|
236
|
+
groups.set(key, [rest]);
|
|
237
|
+
}
|
|
225
238
|
const out = {};
|
|
226
|
-
for (const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
if (cursor === null || typeof cursor !== "object" || Array.isArray(cursor)) {
|
|
230
|
-
cursor = undefined;
|
|
231
|
-
break;
|
|
232
|
-
}
|
|
233
|
-
cursor = cursor[key];
|
|
234
|
-
}
|
|
235
|
-
if (cursor === undefined)
|
|
239
|
+
for (const [key, rests] of groups) {
|
|
240
|
+
const child = value[key];
|
|
241
|
+
if (child === undefined)
|
|
236
242
|
continue;
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
target[key] = {};
|
|
242
|
-
target = target[key];
|
|
243
|
-
}
|
|
244
|
-
target[path[path.length - 1]] = cursor;
|
|
243
|
+
if (rests.some((rest) => rest.length === 0))
|
|
244
|
+
out[key] = child;
|
|
245
|
+
else if (child !== null && typeof child === "object")
|
|
246
|
+
out[key] = project(child, rests);
|
|
245
247
|
}
|
|
246
248
|
return out;
|
|
247
249
|
}
|
|
@@ -292,12 +294,24 @@ function humanError(body, code) {
|
|
|
292
294
|
lines.push(" " + paintErr("dim", (v.path ? v.path + ": " : "") + (v.message ?? "")));
|
|
293
295
|
}
|
|
294
296
|
else if (detail?.body !== undefined) {
|
|
295
|
-
//
|
|
296
|
-
//
|
|
297
|
-
const
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
297
|
+
// Keep every API error and its field visible, even when the headline
|
|
298
|
+
// already used the first message. Unstructured bodies retain a summary.
|
|
299
|
+
const apiErrors = typeof detail.body === "object" && detail.body !== null
|
|
300
|
+
? detail.body.errors : undefined;
|
|
301
|
+
const entries = Array.isArray(apiErrors) ? apiErrors.filter((entry) => entry !== null && typeof entry === "object" && typeof entry.message === "string") : [];
|
|
302
|
+
if (entries.length > 0) {
|
|
303
|
+
for (const entry of entries) {
|
|
304
|
+
const field = typeof entry.field === "string" ? entry.field : "";
|
|
305
|
+
const location = typeof entry.in === "string" ? entry.in + " " : "";
|
|
306
|
+
lines.push(" " + paintErr("dim", (field ? location + field + ": " : "") + entry.message));
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
else {
|
|
310
|
+
const compact = typeof detail.body === "string" ? detail.body : JSON.stringify(detail.body);
|
|
311
|
+
const firstWords = (issue?.message ?? "").slice(0, 40);
|
|
312
|
+
if (compact && compact !== "{}" && !(firstWords && compact.includes(firstWords)))
|
|
313
|
+
lines.push(" " + paintErr("dim", "API said: " + (compact.length > 300 ? compact.slice(0, 297) + "…" : compact)));
|
|
314
|
+
}
|
|
301
315
|
const requestId = detail.request_id ?? detail.body?.request_id ?? detail.body?.requestId;
|
|
302
316
|
if (typeof requestId === "string")
|
|
303
317
|
lines.push(" " + paintErr("dim", "request id: " + requestId));
|
|
@@ -605,7 +619,7 @@ async function startOAuthBrowserSession(parsed, clientId, timeoutMs) {
|
|
|
605
619
|
audience: OAUTH_TOKEN_PARAMS.audience, resource: OAUTH_TOKEN_PARAMS.resource,
|
|
606
620
|
organization: requestedLoginOrganization(parsed.flags),
|
|
607
621
|
}, { signal: controller.signal, timeoutMs, authorize(url) {
|
|
608
|
-
process.stderr.write("Sign in
|
|
622
|
+
process.stderr.write("Sign in with your existing credentials: " + url + "\n");
|
|
609
623
|
if (isAgentMode(parsed) || parsed.flags.get("no-browser") === true)
|
|
610
624
|
process.stderr.write(JSON.stringify({ event: "oauth_browser", authorization_url: url, note: "Open this URL in a browser on the same computer as the CLI." }) + "\n");
|
|
611
625
|
else
|
|
@@ -668,7 +682,6 @@ async function cmdLogin(parsed) {
|
|
|
668
682
|
...AUTH_SCALARS.map((a) => " " + BIN + " login --" + a.flag + " <value>"),
|
|
669
683
|
...(CLI_AUTH_URL ? [" " + BIN + " login approve in the browser: a key is minted for you (add --no-browser to print the link instead of opening it)"] : []),
|
|
670
684
|
" " + BIN + " login --with-token read the credential from stdin (CI)",
|
|
671
|
-
" " + BIN + " login --console-check <file> test browser login for your Typeship Console without replacing saved logins",
|
|
672
685
|
...(HAS_OAUTH_LOGIN ? [" " + BIN + " login --client-id <id> OAuth " + OAUTH_LOGIN_METHOD + " login" + (OAUTH_CLIENT_ID ? " (a default id is built in)" : "")] : []),
|
|
673
686
|
...(HAS_OAUTH_LOGIN ? [" " + BIN + " login --no-browser print the approval URL instead of opening a browser", " " + BIN + " login --device use device authorization when your provider supports it"] : []),
|
|
674
687
|
...(BASIC ? [" " + BIN + " login --username <u> --password <p>"] : []),
|
|
@@ -801,7 +814,7 @@ async function cmdWhoami(parsed) {
|
|
|
801
814
|
if (op) {
|
|
802
815
|
const client = await makeClient(parsed.flags, op);
|
|
803
816
|
const target = client[op.resource];
|
|
804
|
-
const result = await target[op.method]();
|
|
817
|
+
const result = await asApiResult(target[op.method]());
|
|
805
818
|
if (result.ok) {
|
|
806
819
|
out(result.data ?? { ok: true });
|
|
807
820
|
await flushExit(0);
|
|
@@ -963,12 +976,11 @@ async function cmdMcp(parsed) {
|
|
|
963
976
|
" " + BIN + " mcp install --codex Codex CLI (~/.codex/config.toml)",
|
|
964
977
|
" " + BIN + " mcp install --vscode VS Code (./.vscode/mcp.json)",
|
|
965
978
|
" " + BIN + " mcp install --windsurf | --gemini | --opencode | --zed | --claude-desktop",
|
|
966
|
-
" " + BIN + " mcp install --cursor Cursor (./.cursor/mcp.json
|
|
979
|
+
" " + BIN + " mcp install --cursor Cursor (./.cursor/mcp.json)",
|
|
967
980
|
" " + BIN + " mcp --url <https://...> use a remote MCP endpoint instead of the local server",
|
|
968
981
|
" " + BIN + " mcp install --claude --read-only register a read-only server (writes are not callable)",
|
|
969
982
|
"",
|
|
970
983
|
(MCP_URL ? "Default entry: the hosted endpoint " + MCP_URL + " with the auth env var as a reference (never a literal key)." : "Default entry: this package's local stdio server, which reads credentials saved by '" + BIN + " login' or the CLI's auth env vars."),
|
|
971
|
-
"--all skips Cursor until it speaks MCP 2026-07-28.",
|
|
972
984
|
];
|
|
973
985
|
process.stdout.write(lines.join("\n") + "\n");
|
|
974
986
|
await flushExit(0);
|
|
@@ -1066,7 +1078,7 @@ function commandSummaries() {
|
|
|
1066
1078
|
paginated: op.paginated,
|
|
1067
1079
|
destructive: op.safety === "destructive",
|
|
1068
1080
|
auth: op.auth,
|
|
1069
|
-
flags: op.params.filter((p) => p.kind !== "path").map((p) => ({ flag: p.flag, type: p.type, ...(p.items ? { items: p.items } : {}), ...(p.enum ? { enum: p.enum } : {}), required: p.required, ...(p.description ? { description: p.description.split("\n")[0] } : {}) })),
|
|
1081
|
+
flags: op.params.filter((p) => p.kind !== "path").map((p) => ({ flag: p.flag, type: p.type, ...(p.nullable ? { nullable: true } : {}), ...(p.items ? { items: p.items } : {}), ...(p.enum ? { enum: p.enum } : {}), required: p.required, ...(p.description ? { description: p.description.split("\n")[0] } : {}) })),
|
|
1070
1082
|
}));
|
|
1071
1083
|
}
|
|
1072
1084
|
/**
|
|
@@ -1191,7 +1203,7 @@ async function cmdAuth(parsed) {
|
|
|
1191
1203
|
if (op) {
|
|
1192
1204
|
const client = await makeClient(parsed.flags, op);
|
|
1193
1205
|
const target = client[op.resource];
|
|
1194
|
-
const result = await target[op.method]();
|
|
1206
|
+
const result = await asApiResult(target[op.method]());
|
|
1195
1207
|
if (result.ok) {
|
|
1196
1208
|
if (identityConfiguration() && savedIdentity?.identity)
|
|
1197
1209
|
assertApiIdentity(savedIdentity.identity.values, readApiIdentity(result.data, IDENTITY_POLICY));
|
|
@@ -1215,7 +1227,7 @@ async function cmdDoctor(parsed) {
|
|
|
1215
1227
|
}
|
|
1216
1228
|
const checks = [];
|
|
1217
1229
|
const nodeMajor = Number(process.versions.node.split(".")[0]);
|
|
1218
|
-
checks.push({ name: "node", ok: nodeMajor >=
|
|
1230
|
+
checks.push({ name: "node", ok: nodeMajor >= 20, detail: process.version, ...(nodeMajor >= 20 ? {} : { fix: "Install Node 20 or newer." }) });
|
|
1219
1231
|
checks.push({ name: "cli", ok: true, detail: BIN + " " + VERSION + " (" + PKG_NAME + ")" });
|
|
1220
1232
|
let source = null;
|
|
1221
1233
|
let storageProblem;
|
|
@@ -1246,7 +1258,7 @@ async function cmdDoctor(parsed) {
|
|
|
1246
1258
|
try {
|
|
1247
1259
|
const client = await makeClient(parsed.flags, op);
|
|
1248
1260
|
const target = client[op.resource];
|
|
1249
|
-
const result = await target[op.method]();
|
|
1261
|
+
const result = await asApiResult(target[op.method]());
|
|
1250
1262
|
checks.push(result.ok ? { name: "identity", ok: true, detail: op.command.join(" ") + " ok" } : { name: "identity", ok: false, detail: classifyApiError(result.error, { bin: BIN, hadCredential: true, docsUrl: DOCS_URL_DEFAULT }).message, fix: "The credential was rejected; run '" + BIN + " login' with a current one." });
|
|
1251
1263
|
}
|
|
1252
1264
|
catch (e) {
|
|
@@ -1276,7 +1288,7 @@ async function cmdDoctor(parsed) {
|
|
|
1276
1288
|
* init: the one command that connects a machine (or a repo) to this API.
|
|
1277
1289
|
* Stores a credential when given one, installs the skills repository, writes
|
|
1278
1290
|
* MCP config for every agent client found, and upserts a marked block into
|
|
1279
|
-
* AGENTS.md (CLAUDE.md
|
|
1291
|
+
* AGENTS.md (or an existing CLAUDE.md when AGENTS.md is absent). Idempotent; --all takes the
|
|
1280
1292
|
* defaults without asking; every part reports and none of them fails init.
|
|
1281
1293
|
*/
|
|
1282
1294
|
async function cmdInit(parsed) {
|
|
@@ -1288,7 +1300,7 @@ async function cmdInit(parsed) {
|
|
|
1288
1300
|
" --all do everything without prompting (implied under an agent)",
|
|
1289
1301
|
" --no-skills | --no-mcp | --no-agents-md skip a part",
|
|
1290
1302
|
"",
|
|
1291
|
-
"Writes: " + credsPath() + " (credential), the skills directory of each agent on this machine" + (SKILLS_REPO ? " (npx skills add " + SKILLS_REPO + ")" : " (no skills repository configured)") + ", MCP config for detected clients, and a '" + BIN + "' block in ./AGENTS.md.",
|
|
1303
|
+
"Writes: " + credsPath() + " (credential), the skills directory of each agent on this machine" + (SKILLS_REPO ? " (npx skills add " + SKILLS_REPO + ")" : " (no skills repository configured)") + ", MCP config for detected clients, and a '" + BIN + "' block in ./AGENTS.md (or an existing ./CLAUDE.md when AGENTS.md is absent).",
|
|
1292
1304
|
].join("\n") + "\n");
|
|
1293
1305
|
await flushExit(0);
|
|
1294
1306
|
}
|
|
@@ -1361,7 +1373,7 @@ async function cmdInit(parsed) {
|
|
|
1361
1373
|
report.agents_md = { status: "skipped" };
|
|
1362
1374
|
}
|
|
1363
1375
|
else {
|
|
1364
|
-
const file = agentInstructionsFile(cwd
|
|
1376
|
+
const file = agentInstructionsFile(cwd);
|
|
1365
1377
|
const result = upsertAgentBlock(file, BIN + " agent-contract", agentBlock(agentContext(), commandSummaries()));
|
|
1366
1378
|
report.agents_md = { status: result.updated ? "updated" : "written", file: result.file };
|
|
1367
1379
|
}
|
|
@@ -1928,6 +1940,8 @@ function helpSentence(description) {
|
|
|
1928
1940
|
}
|
|
1929
1941
|
/** Type column text for a param: string, number, string[], a|b|c, enum, object, json, path. */
|
|
1930
1942
|
function typeLabel(p) {
|
|
1943
|
+
if (p.nullable)
|
|
1944
|
+
return typeLabel({ ...p, nullable: false }) + "|null";
|
|
1931
1945
|
if (p.type === "file")
|
|
1932
1946
|
return "path (uploaded)";
|
|
1933
1947
|
if (p.format && p.type === "string")
|
|
@@ -2008,7 +2022,7 @@ function printRoot(stream = process.stdout) {
|
|
|
2008
2022
|
}
|
|
2009
2023
|
const width = termWidth();
|
|
2010
2024
|
const lines = [];
|
|
2011
|
-
lines.push(paintOut("bold", BIN) + ": " + "typeship API" + " (v" + "1.0.0" + "), package " + "0.
|
|
2025
|
+
lines.push(paintOut("bold", BIN) + ": " + "typeship API" + " (v" + "1.0.0" + "), package " + "0.21.0");
|
|
2012
2026
|
lines.push("");
|
|
2013
2027
|
lines.push(paintOut("bold", "Usage:") + " " + BIN + " <resource> <command> [args] [--flags]");
|
|
2014
2028
|
lines.push("");
|
|
@@ -2033,7 +2047,7 @@ function printRoot(stream = process.stdout) {
|
|
|
2033
2047
|
lines.push(...labeled("Upgrade: ", "https://typeship.dev/pricing, then regenerate without the operation cap", width, 14));
|
|
2034
2048
|
}
|
|
2035
2049
|
lines.push("");
|
|
2036
|
-
const flagsText = "-v/--version, -h/--help, --debug, --non-interactive, --color on|off|auto, --base-url <url>, --profile <name>, --credentials @<file>|-, --data '<json>', --fields <a,b.c>, --all (paginated lists), --validate (schema-check bodies)" +
|
|
2050
|
+
const flagsText = "-v/--version, -h/--help, --debug, --non-interactive, --color on|off|auto, --base-url <url>, --profile <name>, --credentials @<file>|-, --data '<json>', --fields <a,b.c>, --all (paginated lists), --validate (schema-check parameters and JSON bodies)" +
|
|
2037
2051
|
(AUTH_SCALARS.length > 0 ? ", " + AUTH_SCALARS.map((a) => "--" + a.flag + " <value>").join(", ") : "");
|
|
2038
2052
|
lines.push(...labeled(paintOut("bold", "Global flags:") + " ", flagsText, width, 14).map((l, i) => (i === 0 ? l : l)));
|
|
2039
2053
|
lines.push(...labeled("Credential env vars: ", [
|
|
@@ -2041,7 +2055,7 @@ function printRoot(stream = process.stdout) {
|
|
|
2041
2055
|
...(BASIC ? [BASIC.envUser, BASIC.envPass] : []),
|
|
2042
2056
|
].join(", ") || "none", width, 21));
|
|
2043
2057
|
lines.push(...labeled("Endpoint env var: ", "TYPESHIP_BASE_URL", width, 18));
|
|
2044
|
-
lines.push(...labeled("
|
|
2058
|
+
lines.push(...labeled("Sign-in: ", BIN + " login | logout | whoami | auth check (stored at " + credsPath() + ")", width, 9));
|
|
2045
2059
|
lines.push(...labeled("Setup: ", BIN + " init (connect this machine)" + " | " + BIN + " config (defaults)" + (HAS_MCP || MCP_URL ? " | " + BIN + " mcp install --all (agent clients)" : "") + " | " + BIN + " doctor | " + BIN + " upgrade | " + BIN + " completion <shell>", width, 7));
|
|
2046
2060
|
lines.push(...labeled("Agents: ", BIN + " agent-guide | " + BIN + " help --json | --mode agent | -y/--yes/--force | --out <dir> (JSON errors: {status, issues[{code}], next_steps})", width, 8));
|
|
2047
2061
|
lines.push(...labeled("Docs: ", BIN + " docs [<resource> <command> | search <term> | read <page> | --web]", width, 6));
|
|
@@ -2094,17 +2108,18 @@ function commandExtras(op) {
|
|
|
2094
2108
|
extras.push(["--all", "stream every item from every page (NDJSON)"]);
|
|
2095
2109
|
const collectionField = collectionProperty(op.outputSchema);
|
|
2096
2110
|
extras.push(["--fields <a,b.c>", "keep only these fields of the result" + (op.paginated ? " (per item)" : collectionField ? " (per item in " + collectionField + ")" : "")]);
|
|
2097
|
-
if (bundleProperty(op.outputSchema) !== null)
|
|
2111
|
+
if ((op.fileBundleProperty ?? bundleProperty(op.outputSchema)) !== null)
|
|
2098
2112
|
extras.push(["--out <dir>", "write the response's files ({path, content}) into a directory"]);
|
|
2099
2113
|
if (op.safety === "destructive")
|
|
2100
2114
|
extras.push(["--force, -y", "destructive: required without a terminal, skips the prompt with one"]);
|
|
2101
2115
|
return extras;
|
|
2102
2116
|
}
|
|
2103
|
-
/** One runnable example
|
|
2117
|
+
/** One runnable example from required inputs and authored optional values. */
|
|
2104
2118
|
function exampleLine(op) {
|
|
2105
2119
|
const parts = [BIN, op.command[0], op.command[1]];
|
|
2106
2120
|
for (const p of op.params) {
|
|
2107
|
-
|
|
2121
|
+
const hasExample = p.type !== "file" && Object.hasOwn(op.exampleArguments, p.name);
|
|
2122
|
+
if (!p.required && !hasExample)
|
|
2108
2123
|
continue;
|
|
2109
2124
|
const generated = p.type === "file" ? undefined : op.exampleArguments[p.name];
|
|
2110
2125
|
const values = p.type === "array" ? p.items?.enum : p.enum;
|
|
@@ -2115,7 +2130,7 @@ function exampleLine(op) {
|
|
|
2115
2130
|
: p.type === "object" ? {}
|
|
2116
2131
|
: p.type === "array" ? [p.items?.type === "number" ? 1 : "value"]
|
|
2117
2132
|
: "value";
|
|
2118
|
-
const value = generated
|
|
2133
|
+
const value = hasExample ? generated : fallback;
|
|
2119
2134
|
const sample = typeof value === "string" ? shellQuote(value)
|
|
2120
2135
|
: typeof value === "object" ? shellQuote(JSON.stringify(value))
|
|
2121
2136
|
: String(value);
|
|
@@ -2124,10 +2139,11 @@ function exampleLine(op) {
|
|
|
2124
2139
|
else
|
|
2125
2140
|
parts.push("--" + p.flag, sample);
|
|
2126
2141
|
}
|
|
2127
|
-
const
|
|
2128
|
-
|
|
2129
|
-
|
|
2130
|
-
|
|
2142
|
+
const showBody = op.bodyStyle === "data" && (Object.hasOwn(op.exampleArguments, "body")
|
|
2143
|
+
|| (op.inputSchema.required ?? []).includes("body"));
|
|
2144
|
+
if (showBody) {
|
|
2145
|
+
const body = Object.hasOwn(op.exampleArguments, "body") ? op.exampleArguments.body : {};
|
|
2146
|
+
parts.push(op.bodyKind === "binary" ? "--file ./file" : "--data " + shellQuote(JSON.stringify(body)));
|
|
2131
2147
|
}
|
|
2132
2148
|
if (op.safety === "destructive")
|
|
2133
2149
|
parts.push("--force");
|
|
@@ -2158,6 +2174,9 @@ function printOp(op) {
|
|
|
2158
2174
|
if (op.paginated)
|
|
2159
2175
|
lines.push(" " + usageLine(op) + " --all | jq -r '.id'");
|
|
2160
2176
|
const arrayFlag = rows.find((p) => p.type === "array");
|
|
2177
|
+
if (rows.some((p) => p.nullable)) {
|
|
2178
|
+
lines.push("", "Nullable body flags accept null for JSON null. Use --data to send the literal string null.");
|
|
2179
|
+
}
|
|
2161
2180
|
if (arrayFlag) {
|
|
2162
2181
|
const sample = arrayFlag.items?.enum ? arrayFlag.items.enum.slice(0, 2).join(",") : arrayFlag.items?.type === "number" ? "1,2" : "a,b";
|
|
2163
2182
|
lines.push("", "Array flags take a comma list (--" + arrayFlag.flag + " " + sample + "), the flag repeated, or a JSON array.");
|
|
@@ -2246,6 +2265,8 @@ function coerceScalar(flag, type, enumValues, text) {
|
|
|
2246
2265
|
* Objects must be JSON. Enum values are checked locally.
|
|
2247
2266
|
*/
|
|
2248
2267
|
function coerce(spec, raw, repeated) {
|
|
2268
|
+
if (spec.nullable && raw === "null" && repeated === undefined)
|
|
2269
|
+
return null;
|
|
2249
2270
|
if (spec.type === "file") {
|
|
2250
2271
|
if (raw === true)
|
|
2251
2272
|
fail(2, "--" + spec.flag + " expects a file path");
|
|
@@ -2310,8 +2331,66 @@ function coerce(spec, raw, repeated) {
|
|
|
2310
2331
|
}
|
|
2311
2332
|
return coerceScalar(spec.flag, spec.type === "json" ? "json" : spec.type === "number" ? "number" : "string", spec.enum, text);
|
|
2312
2333
|
}
|
|
2334
|
+
/** Use validation schemas, not the shortened agent-facing schemas: every union
|
|
2335
|
+
* branch and referenced definition must remain valid input. */
|
|
2336
|
+
function validateParameters(op, values, flags) {
|
|
2337
|
+
if (flags.get("validate") !== true)
|
|
2338
|
+
return;
|
|
2339
|
+
const schemas = SCHEMAS[op.resource + "." + op.method]?.params;
|
|
2340
|
+
if (!schemas)
|
|
2341
|
+
return;
|
|
2342
|
+
const violations = [];
|
|
2343
|
+
for (const parameter of op.params) {
|
|
2344
|
+
if (parameter.kind === "body")
|
|
2345
|
+
continue;
|
|
2346
|
+
let value = values[parameter.name];
|
|
2347
|
+
if (value === undefined && parameter.global) {
|
|
2348
|
+
const global = GLOBALS.find((entry) => entry.name === parameter.name);
|
|
2349
|
+
const raw = global ? process.env["TYPESHIP_" + global.envSuffix] : undefined;
|
|
2350
|
+
if (raw !== undefined)
|
|
2351
|
+
value = coerce(parameter, raw);
|
|
2352
|
+
}
|
|
2353
|
+
if (value === undefined)
|
|
2354
|
+
continue;
|
|
2355
|
+
if (parameter.kind === "path")
|
|
2356
|
+
value = coerce(parameter, String(value));
|
|
2357
|
+
const key = parameter.kind + "." + parameter.name;
|
|
2358
|
+
validateAgainstSchema(value, schemas[key], key, violations, DEFS);
|
|
2359
|
+
}
|
|
2360
|
+
if (violations.length)
|
|
2361
|
+
failApi(new ValidationError("request", violations, "parameters"), false);
|
|
2362
|
+
}
|
|
2313
2363
|
/** Whether the last client built carried any credential; failApi tells NO_AUTH from AUTH_INVALID with it. */
|
|
2314
2364
|
let LAST_CLIENT_HAD_CREDENTIAL = false;
|
|
2365
|
+
/** Check the same complete alternatives the request runtime can select, after
|
|
2366
|
+
* per-scheme flag, environment, profile, and OAuth resolution. */
|
|
2367
|
+
function requireOperationCredentials(op, options) {
|
|
2368
|
+
if (op.auth !== "required")
|
|
2369
|
+
return;
|
|
2370
|
+
const supplied = (value) => typeof value === "function" || (typeof value === "string" && value.length > 0)
|
|
2371
|
+
|| (value !== null && typeof value === "object" && "username" in value && "password" in value && typeof value.username === "string" && value.username.length > 0 && typeof value.password === "string" && value.password.length > 0);
|
|
2372
|
+
const named = Object.fromEntries(Object.entries(options.credentials ?? {}).filter(([, value]) => supplied(value)));
|
|
2373
|
+
const available = namedCredentialAvailability(NAMED_SCHEMES, new Set(Object.keys(options).filter((key) => supplied(options[key]))), named);
|
|
2374
|
+
if (op.credentialOptions?.some((alternative) => alternative.length > 0 && alternative.every((option) => available.has(option))))
|
|
2375
|
+
return;
|
|
2376
|
+
const alternatives = (op.credentialOptions ?? []).filter((alternative) => alternative.length > 0 && alternative.every((option) => option.startsWith("credentials.")));
|
|
2377
|
+
const missing = alternatives.map((alternative) => alternative.filter((option) => !available.has(option)).map((option) => option.slice("credentials.".length)));
|
|
2378
|
+
const names = new Set(missing.flat());
|
|
2379
|
+
const relevant = AUTH_SCALARS.filter((scalar) => [...names].some((name) => NAMED_SCHEMES[name]?.options.includes(scalar.option)));
|
|
2380
|
+
const needsBasic = [...names].some((name) => NAMED_SCHEMES[name]?.options.includes("basicAuth"));
|
|
2381
|
+
failWith({
|
|
2382
|
+
status: "action_required",
|
|
2383
|
+
code: "NO_AUTH",
|
|
2384
|
+
message: op.command.join(" ") + " needs one complete credential alternative (" + wireOf(op) + "). " + (missing.length
|
|
2385
|
+
? "Missing security schemes: " + missing.map((names) => names.join(" + ")).join(" OR ") + "."
|
|
2386
|
+
: "The declared security requirements have no supported, compatible alternative in this CLI."),
|
|
2387
|
+
nextSteps: alternatives.length ? [
|
|
2388
|
+
...relevant.map((a) => "Set " + a.env + " in the environment, pass --" + a.flag + " <value>, or run '" + BIN + " login'."),
|
|
2389
|
+
...(needsBasic && BASIC ? ["Set " + BASIC.envUser + " and " + BASIC.envPass + ", or pass --username and --password."] : []),
|
|
2390
|
+
"Supply all schemes in one alternative through " + "TYPESHIP_CREDENTIALS" + " or --credentials @<JSON-file>: " + alternatives.map((alternative) => alternative.map((option) => option.slice("credentials.".length)).join(" + ")).join(" OR ") + ".",
|
|
2391
|
+
] : ["Check the operation's security schemes in the API Spec and regenerate with a supported, compatible alternative."],
|
|
2392
|
+
});
|
|
2393
|
+
}
|
|
2315
2394
|
function validateCredentialsInput(flags) {
|
|
2316
2395
|
const input = flags.get("credentials");
|
|
2317
2396
|
if (BASIC && flags.has("username") !== flags.has("password"))
|
|
@@ -2444,18 +2523,17 @@ async function makeClient(flags, op, candidate, forIdentity = false) {
|
|
|
2444
2523
|
options[g.option] = value;
|
|
2445
2524
|
}
|
|
2446
2525
|
LAST_CLIENT_HAD_CREDENTIAL = Object.keys(options.credentials ?? {}).length > 0 || AUTH_SCALARS.some((a) => options[a.option] !== undefined) || options.basicAuth !== undefined || options.bearerToken !== undefined;
|
|
2447
|
-
|
|
2448
|
-
//
|
|
2449
|
-
//
|
|
2450
|
-
// "non-interactive", so usage by surface does not count CI as agents.
|
|
2451
|
-
// The API can read it back; it carries no secrets.
|
|
2526
|
+
requireOperationCredentials(op, options);
|
|
2527
|
+
// Identify the package and version. Optional harness and caller details
|
|
2528
|
+
// let the API distinguish agent traffic from other non-interactive use.
|
|
2452
2529
|
const harness = detectHarness();
|
|
2453
2530
|
const explicitAgent = flags.get("mode") === "agent" || process.env["TYPESHIP_MODE"] === "agent";
|
|
2454
2531
|
const behaving = agentMode({ flagMode: flags.get("mode"), envMode: process.env["TYPESHIP_MODE"], stdoutIsTTY: process.stdout.isTTY === true, stdinIsTTY: process.stdin.isTTY === true });
|
|
2455
|
-
const caller = harness || explicitAgent ? "
|
|
2532
|
+
const caller = harness || explicitAgent ? "agent" : behaving ? "non-interactive" : null;
|
|
2533
|
+
const details = [harness ? "harness=" + harness : null, caller].filter(Boolean).join("; ");
|
|
2456
2534
|
options.defaultHeaders = {
|
|
2457
2535
|
...options.defaultHeaders,
|
|
2458
|
-
"User-Agent": PKG_NAME + "-cli/" + VERSION +
|
|
2536
|
+
"User-Agent": PKG_NAME + "-cli/" + VERSION + (details ? " (" + details + ")" : ""),
|
|
2459
2537
|
};
|
|
2460
2538
|
if (forIdentity) {
|
|
2461
2539
|
options.fetch = identityFetch(baseUrl);
|
|
@@ -2498,7 +2576,7 @@ function failOmitted(op) {
|
|
|
2498
2576
|
return failWith({
|
|
2499
2577
|
status: "action_required",
|
|
2500
2578
|
code: "PLAN_LIMIT",
|
|
2501
|
-
message: "The command '" + BIN + " " + op.command.join(" ") + "' exists in the API
|
|
2579
|
+
message: "The command '" + BIN + " " + op.command.join(" ") + "' exists in the API Spec but was omitted from this generated package by its plan limit.",
|
|
2502
2580
|
detail: { operation: op.tool, method: op.httpMethod, path: op.path, generated_operations: OPS.length, total_operations: OPS.length + EXCLUDED_OPS },
|
|
2503
2581
|
nextSteps: ["Upgrade at https://typeship.dev/pricing and regenerate the package without the operation cap.", "Do not invent or retry an omitted command against this generated package."],
|
|
2504
2582
|
});
|
|
@@ -2528,8 +2606,8 @@ async function main() {
|
|
|
2528
2606
|
fail(2, "--format json is the only format; output is always JSON.");
|
|
2529
2607
|
}
|
|
2530
2608
|
if (parsed.flags.has("version") || parsed.positionals[0] === "version") {
|
|
2531
|
-
// "
|
|
2532
|
-
//
|
|
2609
|
+
// "acme 1.0.0 (acme 1.0.0)" would say the name twice; when the API's
|
|
2610
|
+
// title is the bin, name the API version as such.
|
|
2533
2611
|
const apiLabel = API_TITLE.toLowerCase().replace(/[^a-z0-9]/g, "") === BIN.toLowerCase().replace(/[^a-z0-9]/g, "") ? "API " + API_VERSION : API_TITLE + " " + API_VERSION;
|
|
2534
2612
|
process.stdout.write(BIN + " " + VERSION + " (" + apiLabel + ", generated by typeship)\n");
|
|
2535
2613
|
await flushExit(0);
|
|
@@ -2697,27 +2775,14 @@ async function main() {
|
|
|
2697
2775
|
fail(2, "--fields expects at least one field path");
|
|
2698
2776
|
}
|
|
2699
2777
|
// --out <dir> materializes a file-shaped response (see cli-agent.ts bundleProperty).
|
|
2700
|
-
const bundleField = bundleProperty(op.outputSchema);
|
|
2778
|
+
const bundleField = op.fileBundleProperty ?? bundleProperty(op.outputSchema);
|
|
2701
2779
|
const collectionField = collectionProperty(op.outputSchema);
|
|
2702
2780
|
const outDir = typeof parsed.flags.get("out") === "string" ? parsed.flags.get("out") : undefined;
|
|
2703
2781
|
if (outDir !== undefined && bundleField === null) {
|
|
2704
2782
|
fail(2, "--out applies to commands whose response carries files ({path, content}); " + op.command.join(" ") + " does not.");
|
|
2705
2783
|
}
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
if (op.auth === "required" && (AUTH_SCALARS.length > 0 || BASIC || HAS_OAUTH_LOGIN) && credentialSource(parsed.flags) === null) {
|
|
2709
|
-
failWith({
|
|
2710
|
-
status: "action_required",
|
|
2711
|
-
code: "NO_AUTH",
|
|
2712
|
-
message: op.command.join(" ") + " needs a credential (" + wireOf(op) + " is authenticated) and none was found.",
|
|
2713
|
-
nextSteps: [
|
|
2714
|
-
...AUTH_SCALARS.map((a) => "Set " + a.env + " in the environment, pass --" + a.flag + " <value>, or run '" + BIN + " login'."),
|
|
2715
|
-
...(BASIC ? ["Set " + BASIC.envUser + " and " + BASIC.envPass + ", or pass --username and --password."] : []),
|
|
2716
|
-
...(AUTH_SCALARS.length === 0 && !BASIC ? ["Run '" + BIN + " login'."] : []),
|
|
2717
|
-
"'" + BIN + " auth check' shows what the CLI would send.",
|
|
2718
|
-
],
|
|
2719
|
-
});
|
|
2720
|
-
}
|
|
2784
|
+
validateParameters(op, values, parsed.flags);
|
|
2785
|
+
const client = await makeClient(parsed.flags, op);
|
|
2721
2786
|
// Destructive commands need --force. A person gets asked; an agent gets
|
|
2722
2787
|
// an action_required envelope with the exact command to run, so nothing
|
|
2723
2788
|
// is deleted on a guess.
|
|
@@ -2736,7 +2801,6 @@ async function main() {
|
|
|
2736
2801
|
if (answer !== "y" && answer !== "yes")
|
|
2737
2802
|
failWith({ status: "action_required", code: "CONFIRMATION_REQUIRED", message: "Cancelled.", nextSteps: ["Run again with --force to skip the prompt: " + rerun] });
|
|
2738
2803
|
}
|
|
2739
|
-
const client = await makeClient(parsed.flags, op);
|
|
2740
2804
|
const selectValue = typeof parsed.flags.get("select") === "string" ? parsed.flags.get("select") : undefined;
|
|
2741
2805
|
const args = buildArgs(op, values, dataBody, selectValue);
|
|
2742
2806
|
const target = client[op.resource];
|
|
@@ -2752,7 +2816,19 @@ async function main() {
|
|
|
2752
2816
|
failApi(e, LAST_CLIENT_HAD_CREDENTIAL);
|
|
2753
2817
|
}
|
|
2754
2818
|
}
|
|
2755
|
-
|
|
2819
|
+
let result = await asApiResult(callResult);
|
|
2820
|
+
if (result.ok && op.httpMethod === "POST" && op.path === "/projects/{project_id}/generate") {
|
|
2821
|
+
const batch = result.data;
|
|
2822
|
+
const generations = client.generations;
|
|
2823
|
+
const completed = [];
|
|
2824
|
+
for (const generation of batch.data) {
|
|
2825
|
+
const waited = await asApiResult(generations.wait(generation.id));
|
|
2826
|
+
if (!waited.ok)
|
|
2827
|
+
failApi(waited.error, LAST_CLIENT_HAD_CREDENTIAL);
|
|
2828
|
+
completed.push(waited.data);
|
|
2829
|
+
}
|
|
2830
|
+
result = { ...result, data: { ...batch, data: completed } };
|
|
2831
|
+
}
|
|
2756
2832
|
if (result.ok) {
|
|
2757
2833
|
if (op.sse) {
|
|
2758
2834
|
// Server-sent events as NDJSON, one line per event, until the stream ends.
|
package/dist/core/http.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Runtime core. Generated by typeship — https://typeship.dev
|
|
3
|
-
* Zero dependencies: built on the platform fetch API (Node
|
|
3
|
+
* Zero dependencies: built on the platform fetch API (Node 20+, browsers, edge).
|
|
4
4
|
*/
|
|
5
5
|
export interface RequestOptions {
|
|
6
6
|
/** Abort the request (composed with the per-attempt timeout). */
|
|
@@ -17,7 +17,7 @@ export interface ResponseMeta {
|
|
|
17
17
|
headers: Headers;
|
|
18
18
|
/** Parsed wire body before it is narrowed to the generated response type.
|
|
19
19
|
* Use this escape hatch for additive fields or variants introduced after
|
|
20
|
-
* this generator
|
|
20
|
+
* this generator version. */
|
|
21
21
|
rawBody?: unknown;
|
|
22
22
|
/** Request identifier from the JSON response body, or from headers for
|
|
23
23
|
* raw and bodyless responses. */
|
|
@@ -37,11 +37,7 @@ export interface RequestContext {
|
|
|
37
37
|
/** 0 on the first try, increments per retry. */
|
|
38
38
|
attempt: number;
|
|
39
39
|
}
|
|
40
|
-
/**
|
|
41
|
-
* Every SDK call returns a discriminated result instead of throwing.
|
|
42
|
-
* Narrow on `ok` and the error side is a typed union of the documented
|
|
43
|
-
* error responses for that exact operation.
|
|
44
|
-
*/
|
|
40
|
+
/** Internal result used by CLI and MCP consumers of the shared core. */
|
|
45
41
|
export type ApiResult<T, E> = {
|
|
46
42
|
ok: true;
|
|
47
43
|
data: T;
|
|
@@ -53,8 +49,23 @@ export type ApiResult<T, E> = {
|
|
|
53
49
|
};
|
|
54
50
|
/** Collapse a result into its data, throwing the typed error when !ok. */
|
|
55
51
|
export declare function unwrap<T, E>(result: ApiResult<T, E>): T;
|
|
52
|
+
/** Adapter for generated CLI and MCP entry points that consume result objects. */
|
|
53
|
+
export declare function asApiResult<T>(call: PromiseLike<T>): Promise<{
|
|
54
|
+
ok: boolean;
|
|
55
|
+
data?: T;
|
|
56
|
+
error?: unknown;
|
|
57
|
+
response?: ResponseMeta;
|
|
58
|
+
}>;
|
|
59
|
+
/** Common fields on every failure. A missing response has status null. */
|
|
60
|
+
export declare class SdkError extends Error {
|
|
61
|
+
readonly code: string;
|
|
62
|
+
readonly status: number | null;
|
|
63
|
+
readonly requestId?: string;
|
|
64
|
+
readonly body: unknown;
|
|
65
|
+
constructor(message: string, code: string, status?: number | null, body?: unknown, requestId?: string);
|
|
66
|
+
}
|
|
56
67
|
/** Base class for every HTTP error response. */
|
|
57
|
-
export declare class ApiError<S extends number = number, B = unknown> extends
|
|
68
|
+
export declare class ApiError<S extends number = number, B = unknown> extends SdkError {
|
|
58
69
|
readonly status: S;
|
|
59
70
|
readonly body: B;
|
|
60
71
|
readonly response: ResponseMeta;
|
|
@@ -65,7 +76,7 @@ export declare class UnexpectedApiError extends ApiError<number, unknown> {
|
|
|
65
76
|
constructor(status: number, body: unknown, response: ResponseMeta);
|
|
66
77
|
}
|
|
67
78
|
/** A successful response declared JSON but carried a body that could not be parsed. */
|
|
68
|
-
export declare class ResponseParseError extends
|
|
79
|
+
export declare class ResponseParseError extends SdkError {
|
|
69
80
|
readonly status: number;
|
|
70
81
|
readonly body: string;
|
|
71
82
|
readonly response: ResponseMeta;
|
|
@@ -76,13 +87,12 @@ export interface Violation {
|
|
|
76
87
|
path: string;
|
|
77
88
|
message: string;
|
|
78
89
|
}
|
|
79
|
-
/** Request or response data did not match the spec's schema
|
|
80
|
-
|
|
81
|
-
* ApiResult, like every other failure. */
|
|
82
|
-
export declare class ValidationError extends Error {
|
|
90
|
+
/** Request or response data did not match the spec's schema. */
|
|
91
|
+
export declare class ValidationError extends SdkError {
|
|
83
92
|
readonly direction: "request" | "response";
|
|
93
|
+
readonly target: "body" | "parameters";
|
|
84
94
|
readonly violations: Violation[];
|
|
85
|
-
constructor(direction: "request" | "response", violations: Violation[]);
|
|
95
|
+
constructor(direction: "request" | "response", violations: Violation[], target?: "body" | "parameters");
|
|
86
96
|
}
|
|
87
97
|
/**
|
|
88
98
|
* Validates against the depth-capped JSON Schema subset emitted in
|
|
@@ -91,9 +101,10 @@ export declare class ValidationError extends Error {
|
|
|
91
101
|
*/
|
|
92
102
|
export declare function validateAgainstSchema(value: unknown, schema: unknown, path: string, out: Violation[], defs?: Record<string, unknown>): void;
|
|
93
103
|
/** The request failed before a complete HTTP response arrived (network failure, timeout, abort, or truncated body). */
|
|
94
|
-
export declare class TransportError extends
|
|
104
|
+
export declare class TransportError extends SdkError {
|
|
95
105
|
readonly cause?: unknown;
|
|
96
|
-
|
|
106
|
+
readonly response?: ResponseMeta;
|
|
107
|
+
constructor(message: string, cause?: unknown, response?: ResponseMeta);
|
|
97
108
|
}
|
|
98
109
|
type ErrorCtor = new (body: any, response: ResponseMeta) => ApiError<number, unknown>;
|
|
99
110
|
export interface CoreRequest {
|
|
@@ -206,6 +217,8 @@ export declare class HttpCore {
|
|
|
206
217
|
/** The client-level value for an x-typeship-globals parameter. */
|
|
207
218
|
globalValue(name: string): unknown;
|
|
208
219
|
request<T, E>(req: CoreRequest): Promise<ApiResult<T, E>>;
|
|
220
|
+
/** SDK-facing call: resolve to the payload or throw its typed error. */
|
|
221
|
+
requestData<T, E>(req: CoreRequest): Promise<T>;
|
|
209
222
|
private send;
|
|
210
223
|
/**
|
|
211
224
|
* The redirect chain, walked here instead of inside fetch, so the header
|
package/dist/core/http.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/core/http.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAC7C,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB;;iCAE6B;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;qCACiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AAElE;8CAC8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;CACjB;AAGD
|
|
1
|
+
{"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/core/http.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAC7C,yEAAyE;IACzE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,OAAO,CAAC;IACjB;;iCAE6B;IAC7B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;qCACiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AAElE;8CAC8C;AAC9C,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC;CACjB;AAGD,wEAAwE;AACxE,MAAM,MAAM,SAAS,CAAC,CAAC,EAAE,CAAC,IACtB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,CAAC,CAAC;IAAC,QAAQ,EAAE,YAAY,CAAA;CAAE,GAC7C;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,CAAC,CAAC;IAAC,QAAQ,CAAC,EAAE,YAAY,CAAA;CAAE,CAAC;AAErD,0EAA0E;AAC1E,wBAAgB,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,GAAG,CAAC,CAIvD;AAED,kFAAkF;AAClF,wBAAsB,WAAW,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,YAAY,CAAA;CAAE,CAAC,CAiBvI;AAED,0EAA0E;AAC1E,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,SAAS,CAAC,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;gBAEX,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,GAAE,MAAM,GAAG,IAAW,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,SAAS,CAAC,EAAE,MAAM;CAQ5G;AA+BD,gDAAgD;AAChD,qBAAa,QAAQ,CAAC,CAAC,SAAS,MAAM,GAAG,MAAM,EAAE,CAAC,GAAG,OAAO,CAAE,SAAQ,QAAQ;IAC5E,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACnB,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACjB,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;gBAEpB,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,QAAQ,EAAE,YAAY;CAMxE;AAED,kDAAkD;AAClD,qBAAa,kBAAmB,SAAQ,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;gBACnD,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY;CAGlE;AAED,uFAAuF;AACvF,qBAAa,kBAAmB,SAAQ,QAAQ;IAC9C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,QAAQ,EAAE,YAAY,CAAC;IAChC,SAAkB,KAAK,CAAC,EAAE,OAAO,CAAC;gBAEtB,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,CAAC,EAAE,OAAO;CAOlE;AAOD,MAAM,WAAW,SAAS;IAAG,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE;AAE5D,gEAAgE;AAChE,qBAAa,eAAgB,SAAQ,QAAQ;IAC3C,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,UAAU,CAAC;IAC3C,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,CAAC;IACvC,QAAQ,CAAC,UAAU,EAAE,SAAS,EAAE,CAAC;gBACrB,SAAS,EAAE,SAAS,GAAG,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,EAAE,MAAM,GAAE,MAAM,GAAG,YAAqB;CAS/G;AAeD;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,EAAE,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAwF3I;AAqBD,uHAAuH;AACvH,qBAAa,cAAe,SAAQ,QAAQ;IAC1C,SAAkB,KAAK,CAAC,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,QAAQ,CAAC,EAAE,YAAY,CAAC;gBAErB,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,YAAY;CAKtE;AAED,KAAK,SAAS,GAAG,KAAK,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,YAAY,KAAK,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAEtF,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACtC,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IAC7C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,WAAW,GAAG,MAAM,GAAG,QAAQ,CAAC;IAC7D,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACnC,qDAAqD;IACrD,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;iDAC6C;IAC7C,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;sEACkE;IAClE,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,OAAO,CAAC,EAAE,cAAc,CAAC;CAC1B;AAED,kFAAkF;AAClF,MAAM,WAAW,WAAW;IAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,sDAAsD;IACtD,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;CACnC;AA2BD,MAAM,WAAW,UAAU;IACzB,0EAA0E;IAC1E,WAAW,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC;IACjD,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACnC,kEAAkE;IAClE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;IACjC,KAAK,EAAE,OAAO,KAAK,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,yEAAyE;IACzE,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9D;qDACiD;IACjD,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnF;;6BAEyB;IACzB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9F;sDACkD;IAClD,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;IACpC;;yCAEqC;IACrC,QAAQ,CAAC,EAAE;QAAE,QAAQ,EAAE,OAAO,CAAC;QAAC,SAAS,EAAE,OAAO,CAAC;QAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAAA;KAAE,CAAC;IAC7E,4EAA4E;IAC5E,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE;QAAE,GAAG,CAAC,EAAE,OAAO,CAAC;QAAC,GAAG,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IAC3D,gEAAgE;IAChE,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,yEAAyE;IACzE,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC;;;yBAGqB;IACrB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;CACxB;AAED,gEAAgE;AAChE,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,yCAAyC;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA0BD,qBAAa,QAAQ;IACnB,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,6DAA6D;IAC7D,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAW;IAC5C;iDAC6C;IAC7C,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAU;gBAG9B,MAAM,EAAE,UAAU;IAa9B,kEAAkE;IAClE,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO;IAI5B,OAAO,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IA6J/D,wEAAwE;IAClE,WAAW,CAAC,CAAC,EAAE,CAAC,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC;YAIvC,IAAI;IAoDlB;;;;;;;;;;;;OAYG;YACW,eAAe;YA+Cf,QAAQ;CAiBvB;AAOD,wEAAwE;AACxE,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,UAAU,GAAG,MAAM,CAOxE;AAED,+EAA+E;AAC/E,wBAAgB,UAAU,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAKtD;AA0HD,wBAAgB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAI9C"}
|