@typeship-ax/cli 0.22.0 → 0.23.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +12 -8
- package/README.md +14 -27
- package/api.json +8898 -9026
- package/api.md +369 -327
- package/dist/arguments.d.ts +47 -0
- package/dist/arguments.d.ts.map +1 -0
- package/dist/arguments.js +254 -0
- package/dist/cli-agent.d.ts +31 -8
- package/dist/cli-agent.d.ts.map +1 -1
- package/dist/cli-agent.js +146 -28
- package/dist/cli.js +483 -237
- package/dist/core/http.d.ts +162 -19
- package/dist/core/http.d.ts.map +1 -1
- package/dist/core/http.js +381 -48
- package/dist/core/pagination.d.ts +42 -6
- package/dist/core/pagination.d.ts.map +1 -1
- package/dist/core/pagination.js +111 -17
- package/dist/credential-storage.d.ts +10 -3
- package/dist/credential-storage.d.ts.map +1 -1
- package/dist/credential-storage.js +15 -6
- package/dist/dates.d.ts +1 -1
- package/dist/dates.js +1 -1
- package/dist/errors.d.ts +20 -84
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +20 -108
- package/dist/fields.d.ts +29 -0
- package/dist/fields.d.ts.map +1 -0
- package/dist/fields.js +101 -0
- package/dist/index.d.ts +28 -18
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +35 -25
- package/dist/named-credentials.d.ts +19 -0
- package/dist/named-credentials.d.ts.map +1 -1
- package/dist/named-credentials.js +81 -1
- package/dist/oauth-login.d.ts +8 -2
- package/dist/oauth-login.d.ts.map +1 -1
- package/dist/oauth-login.js +31 -19
- package/dist/oauth-request.d.ts +7 -1
- package/dist/oauth-request.d.ts.map +1 -1
- package/dist/oauth-request.js +26 -4
- package/dist/oauth-session.d.ts +13 -1
- package/dist/oauth-session.d.ts.map +1 -1
- package/dist/oauth-session.js +34 -18
- package/dist/ops.d.ts +53 -5
- package/dist/ops.d.ts.map +1 -1
- package/dist/ops.js +49 -40
- package/dist/polling-login.d.ts +8 -2
- package/dist/polling-login.d.ts.map +1 -1
- package/dist/polling-login.js +25 -11
- package/dist/resources/api-keys.d.ts +10 -7
- package/dist/resources/api-keys.d.ts.map +1 -1
- package/dist/resources/api-keys.js +10 -31
- package/dist/resources/deliveries.d.ts +88 -4
- package/dist/resources/deliveries.d.ts.map +1 -1
- package/dist/resources/deliveries.js +95 -18
- package/dist/resources/drafts.d.ts +15 -15
- package/dist/resources/drafts.d.ts.map +1 -1
- package/dist/resources/drafts.js +11 -64
- package/dist/resources/files.d.ts +4 -4
- package/dist/resources/files.d.ts.map +1 -1
- package/dist/resources/files.js +3 -12
- package/dist/resources/generations.d.ts +14 -14
- package/dist/resources/generations.d.ts.map +1 -1
- package/dist/resources/generations.js +21 -45
- package/dist/resources/organization.d.ts +4 -4
- package/dist/resources/organization.d.ts.map +1 -1
- package/dist/resources/organization.js +3 -10
- package/dist/resources/{generate.d.ts → packages.d.ts} +16 -16
- package/dist/resources/packages.d.ts.map +1 -0
- package/dist/resources/{generate.js → packages.js} +13 -29
- package/dist/resources/projects.d.ts +50 -50
- package/dist/resources/projects.d.ts.map +1 -1
- package/dist/resources/projects.js +60 -116
- package/dist/resources/releases.d.ts +21 -16
- package/dist/resources/releases.d.ts.map +1 -1
- package/dist/resources/releases.js +18 -39
- package/dist/resources/spec-revisions.d.ts +15 -6
- package/dist/resources/spec-revisions.d.ts.map +1 -1
- package/dist/resources/spec-revisions.js +6 -28
- package/dist/resources/specs.d.ts +7 -7
- package/dist/resources/specs.d.ts.map +1 -1
- package/dist/resources/specs.js +6 -34
- package/dist/resources/targets.d.ts +48 -48
- package/dist/resources/targets.d.ts.map +1 -1
- package/dist/resources/targets.js +58 -114
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +83 -81
- package/dist/search.d.ts +54 -0
- package/dist/search.d.ts.map +1 -0
- package/dist/search.js +421 -0
- package/dist/types.d.ts +499 -339
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +18 -18
- package/package.json +5 -2
- package/src/arguments.ts +242 -0
- package/src/cli-agent.ts +156 -30
- package/src/cli.ts +444 -211
- package/src/core/http.ts +457 -58
- package/src/core/pagination.ts +129 -18
- package/src/credential-storage.ts +16 -6
- package/src/dates.ts +1 -1
- package/src/errors.ts +46 -115
- package/src/fields.ts +91 -0
- package/src/index.ts +45 -28
- package/src/named-credentials.ts +66 -1
- package/src/oauth-login.ts +36 -21
- package/src/oauth-request.ts +32 -6
- package/src/oauth-session.ts +37 -19
- package/src/ops.ts +82 -44
- package/src/polling-login.ts +24 -11
- package/src/resources/api-keys.ts +34 -48
- package/src/resources/deliveries.ts +211 -30
- package/src/resources/drafts.ts +60 -107
- package/src/resources/files.ts +19 -20
- package/src/resources/generations.ts +57 -75
- package/src/resources/organization.ts +11 -16
- package/src/resources/{generate.ts → packages.ts} +43 -51
- package/src/resources/projects.ts +145 -200
- package/src/resources/releases.ts +48 -65
- package/src/resources/spec-revisions.ts +38 -47
- package/src/resources/specs.ts +39 -59
- package/src/resources/targets.ts +143 -193
- package/src/schemas.ts +83 -81
- package/src/search.ts +434 -0
- package/src/types.ts +538 -357
- package/dist/console-login-check.d.ts +0 -21
- package/dist/console-login-check.d.ts.map +0 -1
- package/dist/console-login-check.js +0 -107
- package/dist/console-login-contract.d.ts +0 -45
- package/dist/console-login-contract.d.ts.map +0 -1
- package/dist/console-login-contract.js +0 -40
- package/dist/resources/generate.d.ts.map +0 -1
- package/dist/resources/publications.d.ts +0 -47
- package/dist/resources/publications.d.ts.map +0 -1
- package/dist/resources/publications.js +0 -70
- package/src/console-login-check.ts +0 -88
- package/src/console-login-contract.ts +0 -65
- package/src/resources/publications.ts +0 -140
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import { type ConsoleLoginCheck, type ConsoleLoginConfiguration } from "./console-login-contract.js";
|
|
2
|
-
import { type OAuthLoginSession } from "./oauth-login.js";
|
|
3
|
-
import { type CredentialSchemes, type NamedCredentials } from "./named-credentials.js";
|
|
4
|
-
/** No traffic to Typeship occurs without the explicit --console-check action.
|
|
5
|
-
* Only the credentials selected for the identity read leave this process;
|
|
6
|
-
* refresh tokens and other stored logins are never sent to the Console. */
|
|
7
|
-
export declare function checkConsoleBrowserLogin(input: {
|
|
8
|
-
file: string;
|
|
9
|
-
configuration: ConsoleLoginConfiguration;
|
|
10
|
-
schemes: CredentialSchemes;
|
|
11
|
-
credentials: NamedCredentials;
|
|
12
|
-
login(timeoutMs: number): Promise<OAuthLoginSession>;
|
|
13
|
-
verify(credentials: NamedCredentials, expectations: ConsoleLoginCheck["expectations"]): Promise<void>;
|
|
14
|
-
progress(message: string): void;
|
|
15
|
-
}): Promise<{
|
|
16
|
-
ok: true;
|
|
17
|
-
method: "oauth_browser";
|
|
18
|
-
console_verified: true;
|
|
19
|
-
revoked: boolean | null;
|
|
20
|
-
}>;
|
|
21
|
-
//# sourceMappingURL=console-login-check.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"console-login-check.d.ts","sourceRoot":"","sources":["../src/console-login-check.ts"],"names":[],"mappings":"AAEA,OAAO,EAAgE,KAAK,iBAAiB,EAAE,KAAK,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AACnK,OAAO,EAAE,KAAK,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC1D,OAAO,EAAyB,KAAK,iBAAiB,EAAE,KAAK,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAuB9G;;2EAE2E;AAC3E,wBAAsB,wBAAwB,CAAC,KAAK,EAAE;IACpD,IAAI,EAAE,MAAM,CAAC;IACb,aAAa,EAAE,yBAAyB,CAAC;IACzC,OAAO,EAAE,iBAAiB,CAAC;IAC3B,WAAW,EAAE,gBAAgB,CAAC;IAC9B,KAAK,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,CAAC,CAAC;IACrD,MAAM,CAAC,WAAW,EAAE,gBAAgB,EAAE,YAAY,EAAE,iBAAiB,CAAC,cAAc,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtG,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC,GAAG,OAAO,CAAC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,eAAe,CAAC;IAAC,gBAAgB,EAAE,IAAI,CAAC;IAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAA;CAAE,CAAC,CAiDlG"}
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import { openSync, readSync, closeSync, fstatSync, constants } from "node:fs";
|
|
2
|
-
import { oauthJsonRequest } from "./oauth-request.js";
|
|
3
|
-
import { sameConsoleLoginConfiguration, matchesConsoleBrowserEvidence } from "./console-login-contract.js";
|
|
4
|
-
import { parseNamedCredentials } from "./named-credentials.js";
|
|
5
|
-
function readCheck(path) {
|
|
6
|
-
let fd;
|
|
7
|
-
try {
|
|
8
|
-
fd = openSync(path, constants.O_RDONLY | constants.O_NONBLOCK);
|
|
9
|
-
if (!fstatSync(fd).isFile())
|
|
10
|
-
throw new Error();
|
|
11
|
-
const buffer = Buffer.alloc(65_537);
|
|
12
|
-
let size = 0;
|
|
13
|
-
while (size < buffer.length) {
|
|
14
|
-
const n = readSync(fd, buffer, size, buffer.length - size, null);
|
|
15
|
-
if (!n)
|
|
16
|
-
break;
|
|
17
|
-
size += n;
|
|
18
|
-
}
|
|
19
|
-
if (size > 65_536)
|
|
20
|
-
throw new Error();
|
|
21
|
-
const value = JSON.parse(buffer.subarray(0, size).toString("utf8"));
|
|
22
|
-
if (value.version !== 1 || typeof value.ticket !== "string" || !/^[A-Za-z0-9_-]{43}$/.test(value.ticket) || !value.configuration || !Array.isArray(value.expectations) || !value.expectations.length || value.expectations.length > 3)
|
|
23
|
-
throw new Error();
|
|
24
|
-
const endpoint = new URL(value.endpoint);
|
|
25
|
-
const development = endpoint.protocol === "http:" && ["127.0.0.1", "[::1]"].includes(endpoint.hostname);
|
|
26
|
-
if (!(endpoint.origin === "https://typeship.dev" || development) || endpoint.pathname !== "/api/authentication/browser" || endpoint.username || endpoint.password || endpoint.search || endpoint.hash)
|
|
27
|
-
throw new Error();
|
|
28
|
-
const remaining = Date.parse(value.expiresAt) - Date.now();
|
|
29
|
-
if (!Number.isFinite(remaining) || remaining <= 0 || remaining > 600_000)
|
|
30
|
-
throw new Error();
|
|
31
|
-
return value;
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
throw new Error("Download a new login check from your Typeship Console and pass its JSON file to --console-check. Checks expire after ten minutes.");
|
|
35
|
-
}
|
|
36
|
-
finally {
|
|
37
|
-
if (fd !== undefined)
|
|
38
|
-
closeSync(fd);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
/** No traffic to Typeship occurs without the explicit --console-check action.
|
|
42
|
-
* Only the credentials selected for the identity read leave this process;
|
|
43
|
-
* refresh tokens and other stored logins are never sent to the Console. */
|
|
44
|
-
export async function checkConsoleBrowserLogin(input) {
|
|
45
|
-
const check = readCheck(input.file);
|
|
46
|
-
if (!sameConsoleLoginConfiguration(input.configuration, check.configuration))
|
|
47
|
-
throw new Error("This CLI's authentication settings do not match the saved Target. Regenerate the CLI, select the matching environment, and download a new check.");
|
|
48
|
-
const send = async (body, timeoutMs = 30_000) => {
|
|
49
|
-
const response = await oauthJsonRequest(check.endpoint, { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json" }, body: JSON.stringify({ ticket: check.ticket, ...body }) }, timeoutMs);
|
|
50
|
-
if (response.status === 422)
|
|
51
|
-
throw new Error("Typeship could not verify this login. Check the expected identity, API permissions and saved Target settings, then download a new check.");
|
|
52
|
-
if (response.status !== 200 || response.data?.ok !== true)
|
|
53
|
-
throw new Error("The Console check expired, was already used, changed, or could not be completed. Download a new check and try again.");
|
|
54
|
-
return response.data;
|
|
55
|
-
};
|
|
56
|
-
await send({ action: "inspect" });
|
|
57
|
-
let revoked = null;
|
|
58
|
-
try {
|
|
59
|
-
const supplied = parseNamedCredentials(input.credentials, input.schemes);
|
|
60
|
-
// Only a complete alternative that uses the fresh browser token proves
|
|
61
|
-
// browser access. An unrelated key-only alternative is not sufficient.
|
|
62
|
-
const requirement = input.configuration.requirements.find((entry) => {
|
|
63
|
-
const names = Object.keys(entry);
|
|
64
|
-
if (!names.some((name) => input.schemes[name]?.kind === "bearer") || !names.every((name) => input.schemes[name]?.kind === "bearer" || supplied[name] !== undefined))
|
|
65
|
-
return false;
|
|
66
|
-
const selected = input.configuration.requirements.find((candidate) => Object.keys(candidate).every((name) => names.includes(name)));
|
|
67
|
-
return selected && Object.keys(selected).some((name) => input.schemes[name]?.kind === "bearer");
|
|
68
|
-
});
|
|
69
|
-
if (!requirement)
|
|
70
|
-
throw new Error("Supply the additional named credentials required by the identity read with --credentials @file or environment variables.");
|
|
71
|
-
input.progress("This check runs a temporary browser login. Typeship will receive only the access token and any additional credentials required for the identity read; refresh tokens stay on this computer.");
|
|
72
|
-
const session = await input.login(Math.max(1, Date.parse(check.expiresAt) - Date.now()));
|
|
73
|
-
try {
|
|
74
|
-
const evidence = { method: "oauth_browser", issuer: session.issuer, clientId: session.clientId, redirectUri: session.redirectUri };
|
|
75
|
-
if (!matchesConsoleBrowserEvidence(input.configuration, evidence))
|
|
76
|
-
throw new Error("The browser login did not use the Target's client registration and native callback.");
|
|
77
|
-
const credentials = Object.fromEntries(Object.keys(requirement).map((name) => [name, input.schemes[name].kind === "bearer" ? session.accessToken : supplied[name]]));
|
|
78
|
-
await input.verify(credentials, check.expectations);
|
|
79
|
-
await send({ action: "complete", configuration: input.configuration, evidence, credentials, expectations: check.expectations });
|
|
80
|
-
}
|
|
81
|
-
finally {
|
|
82
|
-
// Verification sessions never replace the customer's saved login.
|
|
83
|
-
// Revoke the temporary grant when the provider advertises an endpoint.
|
|
84
|
-
if (session.revocationUrl) {
|
|
85
|
-
try {
|
|
86
|
-
const response = await fetch(session.revocationUrl, { method: "POST", redirect: "error", credentials: "omit", signal: AbortSignal.timeout(10_000), headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ token: session.refreshToken ?? session.accessToken, token_type_hint: session.refreshToken ? "refresh_token" : "access_token", client_id: session.clientId }) });
|
|
87
|
-
void response.body?.cancel().catch(() => { });
|
|
88
|
-
revoked = response.status === 200;
|
|
89
|
-
}
|
|
90
|
-
catch {
|
|
91
|
-
revoked = false;
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
catch (error) {
|
|
97
|
-
// Report only that the attempt ended. Never send provider errors, identity
|
|
98
|
-
// values or credentials, and never replace the original local error. A
|
|
99
|
-
// consumed check rejects this report, preserving any completed API proof.
|
|
100
|
-
try {
|
|
101
|
-
await send({ action: "fail" }, 5_000);
|
|
102
|
-
}
|
|
103
|
-
catch { /* Best effort; the Console can still expire the check. */ }
|
|
104
|
-
throw error;
|
|
105
|
-
}
|
|
106
|
-
return { ok: true, method: "oauth_browser", console_verified: true, revoked };
|
|
107
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
export interface ConsoleLoginConfiguration {
|
|
2
|
-
baseUrl: string;
|
|
3
|
-
environment: string | null;
|
|
4
|
-
operation: string;
|
|
5
|
-
request: {
|
|
6
|
-
method: string;
|
|
7
|
-
path: string;
|
|
8
|
-
graphqlField: string | null;
|
|
9
|
-
graphqlQuery: string | null;
|
|
10
|
-
};
|
|
11
|
-
requirements: Record<string, string[]>[];
|
|
12
|
-
issuer: string;
|
|
13
|
-
clientId: string;
|
|
14
|
-
discoveryUrl: string | null;
|
|
15
|
-
authorizationUrl: string | null;
|
|
16
|
-
tokenUrl: string | null;
|
|
17
|
-
redirectUri: string;
|
|
18
|
-
scopes: string[];
|
|
19
|
-
audience: string | null;
|
|
20
|
-
resource: string | null;
|
|
21
|
-
}
|
|
22
|
-
export interface ConsoleIdentityExpectation {
|
|
23
|
-
kind: "account" | "organization" | "user";
|
|
24
|
-
pointer: string;
|
|
25
|
-
expected: string | number;
|
|
26
|
-
}
|
|
27
|
-
export interface ConsoleLoginCheck {
|
|
28
|
-
version: 1;
|
|
29
|
-
endpoint: string;
|
|
30
|
-
ticket: string;
|
|
31
|
-
expiresAt: string;
|
|
32
|
-
configuration: ConsoleLoginConfiguration;
|
|
33
|
-
expectations: ConsoleIdentityExpectation[];
|
|
34
|
-
}
|
|
35
|
-
export interface ConsoleBrowserEvidence {
|
|
36
|
-
method: "oauth_browser";
|
|
37
|
-
issuer: string;
|
|
38
|
-
clientId: string;
|
|
39
|
-
redirectUri: string;
|
|
40
|
-
}
|
|
41
|
-
/** Compare the generated product's own settings with the reviewed check.
|
|
42
|
-
* The downloaded file never supplies the CLI's OAuth or API destination. */
|
|
43
|
-
export declare function sameConsoleLoginConfiguration(left: ConsoleLoginConfiguration, right: ConsoleLoginConfiguration): boolean;
|
|
44
|
-
export declare function matchesConsoleBrowserEvidence(config: ConsoleLoginConfiguration, evidence: ConsoleBrowserEvidence): boolean;
|
|
45
|
-
//# sourceMappingURL=console-login-contract.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"console-login-contract.d.ts","sourceRoot":"","sources":["../src/console-login-contract.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,yBAAyB;IACxC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC;IACpG,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AACD,MAAM,WAAW,0BAA0B;IACzC,IAAI,EAAE,SAAS,GAAG,cAAc,GAAG,MAAM,CAAC;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,MAAM,CAAC;CAC3B;AACD,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,CAAC,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,yBAAyB,CAAC;IACzC,YAAY,EAAE,0BAA0B,EAAE,CAAC;CAC5C;AACD,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,eAAe,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;CACrB;AAQD;4EAC4E;AAC5E,wBAAgB,6BAA6B,CAAC,IAAI,EAAE,yBAAyB,EAAE,KAAK,EAAE,yBAAyB,GAAG,OAAO,CAOxH;AAED,wBAAgB,6BAA6B,CAAC,MAAM,EAAE,yBAAyB,EAAE,QAAQ,EAAE,sBAAsB,GAAG,OAAO,CAU1H"}
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
function canonical(value) {
|
|
2
|
-
if (Array.isArray(value))
|
|
3
|
-
return "[" + value.map(canonical).join(",") + "]";
|
|
4
|
-
if (value && typeof value === "object")
|
|
5
|
-
return "{" + Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, item]) => JSON.stringify(key) + ":" + canonical(item)).join(",") + "}";
|
|
6
|
-
return JSON.stringify(value) ?? "null";
|
|
7
|
-
}
|
|
8
|
-
/** Compare the generated product's own settings with the reviewed check.
|
|
9
|
-
* The downloaded file never supplies the CLI's OAuth or API destination. */
|
|
10
|
-
export function sameConsoleLoginConfiguration(left, right) {
|
|
11
|
-
const normalize = (value) => ({ ...value,
|
|
12
|
-
baseUrl: new URL(value.baseUrl).href,
|
|
13
|
-
scopes: [...new Set(value.scopes)].sort(),
|
|
14
|
-
requirements: value.requirements.map((entry) => Object.fromEntries(Object.entries(entry).map(([key, scopes]) => [key, [...new Set(scopes)].sort()]))),
|
|
15
|
-
});
|
|
16
|
-
try {
|
|
17
|
-
return canonical(normalize(left)) === canonical(normalize(right));
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
return false;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
export function matchesConsoleBrowserEvidence(config, evidence) {
|
|
24
|
-
try {
|
|
25
|
-
if (evidence.method !== "oauth_browser" || evidence.issuer !== config.issuer || evidence.clientId !== config.clientId)
|
|
26
|
-
return false;
|
|
27
|
-
const configured = new URL(config.redirectUri), actual = new URL(evidence.redirectUri);
|
|
28
|
-
if (configured.protocol !== "http:" || !["127.0.0.1", "[::1]"].includes(configured.hostname) || configured.username || configured.password || configured.search || configured.hash)
|
|
29
|
-
return false;
|
|
30
|
-
if (configured.port && configured.port !== actual.port)
|
|
31
|
-
return false;
|
|
32
|
-
if (!actual.port)
|
|
33
|
-
return false;
|
|
34
|
-
configured.port = actual.port;
|
|
35
|
-
return configured.href === actual.href;
|
|
36
|
-
}
|
|
37
|
-
catch {
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
40
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/resources/generate.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,aAAa,EACb,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,iBAAiB,EACjB,wBAAwB,EACzB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,eAAe,EAAoB,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAE3F,qBAAa,gBAAgB;IACf,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,QAAQ;IAC5C;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACG,GAAG,CACP,IAAI,EAAE,eAAe,EACrB,MAAM,CAAC,EAAE,iBAAiB,EAC1B,OAAO,CAAC,EAAE,cAAc,GACvB,OAAO,CAAC,oBAAoB,CAAC;IA0BhC;;;;;;;;;;;;OAYG;IACG,eAAe,CAAC,MAAM,EAAE,6BAA6B,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;CAmBtG;AAED,MAAM,WAAW,iBAAiB;IAChC;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,oCAAoC;AACpC,MAAM,MAAM,gBAAgB,GACxB,eAAe,GACf,iBAAiB,GACjB,cAAc,GACd,aAAa,GACb,oBAAoB,GACpB,wBAAwB,GACxB,gBAAgB,GAChB,mBAAmB,GACnB,gBAAgB,GAChB,kBAAkB,GAClB,kBAAkB,GAClB,cAAc,GACd,eAAe,CAAC;AAEpB,MAAM,WAAW,6BAA6B;IAC5C,yEAAyE;IACzE,KAAK,EAAE,MAAM,CAAC;CACf;AAED,gDAAgD;AAChD,MAAM,MAAM,4BAA4B,GACpC,eAAe,GACf,aAAa,GACb,gBAAgB,GAChB,mBAAmB,GACnB,kBAAkB,GAClB,kBAAkB,GAClB,cAAc,GACd,eAAe,CAAC"}
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import { HttpCore, type RequestOptions } from "../core/http.js";
|
|
2
|
-
import { PagePromise } from "../core/pagination.js";
|
|
3
|
-
import { ResponseParseError, TransportError, UnexpectedApiError, ValidationError, BadRequestError, ForbiddenError, InternalServerError, NotFoundError, RateLimitedError, UnauthorizedError } from "../errors.js";
|
|
4
|
-
import type { PublicationId, PublicationRead, PublicationResponseRead, ReleaseId } from "../types.js";
|
|
5
|
-
export declare class PublicationsResource {
|
|
6
|
-
private readonly _core;
|
|
7
|
-
constructor(_core: HttpCore);
|
|
8
|
-
/**
|
|
9
|
-
* List publications
|
|
10
|
-
*
|
|
11
|
-
* Auto-paginates: `for await (const item of …)` walks every page.
|
|
12
|
-
* `GET /publications`
|
|
13
|
-
*/
|
|
14
|
-
list(params?: PublicationsListParams, options?: RequestOptions): PagePromise<PublicationRead, PublicationsListError>;
|
|
15
|
-
/**
|
|
16
|
-
* Get publishing status
|
|
17
|
-
*
|
|
18
|
-
* Returns the registry publishing status for a release. A status in another organization returns
|
|
19
|
-
* 404 resource_not_found.
|
|
20
|
-
* `GET /publications/{publication_id}`
|
|
21
|
-
*/
|
|
22
|
-
get(publicationId: PublicationId, options?: RequestOptions): Promise<PublicationResponseRead>;
|
|
23
|
-
}
|
|
24
|
-
export interface PublicationsListParams {
|
|
25
|
-
/**
|
|
26
|
-
* Maximum number of resources to return. Omit for 20; otherwise supply base-10 digits
|
|
27
|
-
* representing an integer from 1 to 100. Empty, malformed, or out-of-range values return 400
|
|
28
|
-
* input_invalid. List query parameters must appear only once; repeated or unrecognized parameters
|
|
29
|
-
* return 400 query_param_invalid.
|
|
30
|
-
*/
|
|
31
|
-
limit?: number;
|
|
32
|
-
/**
|
|
33
|
-
* Opaque cursor from the preceding page's next_cursor. Valid only for the same organization,
|
|
34
|
-
* operation, filters, and ordering that issued it. Omit to start at the first page. Empty or
|
|
35
|
-
* malformed cursors, and cursors issued for different filters, return 400 cursor_invalid; start
|
|
36
|
-
* again from the first page. Repeated cursors return 400 query_param_invalid. The page limit may
|
|
37
|
-
* change between requests.
|
|
38
|
-
*/
|
|
39
|
-
cursor?: string;
|
|
40
|
-
/** Only publications of this release. */
|
|
41
|
-
releaseId?: ReleaseId;
|
|
42
|
-
}
|
|
43
|
-
/** Typed errors `list` can throw. */
|
|
44
|
-
export type PublicationsListError = BadRequestError | UnauthorizedError | ForbiddenError | NotFoundError | RateLimitedError | InternalServerError | UnexpectedApiError | ResponseParseError | TransportError | ValidationError;
|
|
45
|
-
/** Typed errors `get` can throw. */
|
|
46
|
-
export type PublicationsGetError = UnauthorizedError | ForbiddenError | NotFoundError | RateLimitedError | InternalServerError | UnexpectedApiError | ResponseParseError | TransportError | ValidationError;
|
|
47
|
-
//# sourceMappingURL=publications.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"publications.d.ts","sourceRoot":"","sources":["../../src/resources/publications.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,KAAK,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAChE,OAAO,EAAY,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAC9D,OAAO,EACL,kBAAkB,EAClB,cAAc,EACd,kBAAkB,EAClB,eAAe,EACf,eAAe,EACf,cAAc,EACd,mBAAmB,EACnB,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EAClB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAEV,aAAa,EAGb,eAAe,EAEf,uBAAuB,EACvB,SAAS,EACV,MAAM,aAAa,CAAC;AAErB,qBAAa,oBAAoB;IACnB,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,QAAQ;IAC5C;;;;;OAKG;IACH,IAAI,CACF,MAAM,CAAC,EAAE,sBAAsB,EAC/B,OAAO,CAAC,EAAE,cAAc,GACvB,WAAW,CAAC,eAAe,EAAE,qBAAqB,CAAC;IA+BtD;;;;;;OAMG;IACG,GAAG,CAAC,aAAa,EAAE,aAAa,EAAE,OAAO,CAAC,EAAE,cAAc,GAAG,OAAO,CAAC,uBAAuB,CAAC;CAiBpG;AAED,MAAM,WAAW,sBAAsB;IACrC;;;;;OAKG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;;;OAMG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,yCAAyC;IACzC,SAAS,CAAC,EAAE,SAAS,CAAC;CACvB;AAED,qCAAqC;AACrC,MAAM,MAAM,qBAAqB,GAC7B,eAAe,GACf,iBAAiB,GACjB,cAAc,GACd,aAAa,GACb,gBAAgB,GAChB,mBAAmB,GACnB,kBAAkB,GAClB,kBAAkB,GAClB,cAAc,GACd,eAAe,CAAC;AAEpB,oCAAoC;AACpC,MAAM,MAAM,oBAAoB,GAC5B,iBAAiB,GACjB,cAAc,GACd,aAAa,GACb,gBAAgB,GAChB,mBAAmB,GACnB,kBAAkB,GAClB,kBAAkB,GAClB,cAAc,GACd,eAAe,CAAC"}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
// typeship — publications resource.
|
|
2
|
-
// Generated by typeship — https://typeship.dev
|
|
3
|
-
import { paginate } from "../core/pagination.js";
|
|
4
|
-
import { BadRequestError, ForbiddenError, InternalServerError, NotFoundError, RateLimitedError, UnauthorizedError, } from "../errors.js";
|
|
5
|
-
export class PublicationsResource {
|
|
6
|
-
_core;
|
|
7
|
-
constructor(_core) {
|
|
8
|
-
this._core = _core;
|
|
9
|
-
}
|
|
10
|
-
/**
|
|
11
|
-
* List publications
|
|
12
|
-
*
|
|
13
|
-
* Auto-paginates: `for await (const item of …)` walks every page.
|
|
14
|
-
* `GET /publications`
|
|
15
|
-
*/
|
|
16
|
-
list(params, options) {
|
|
17
|
-
return paginate(this._core, {
|
|
18
|
-
method: "GET",
|
|
19
|
-
path: "/publications",
|
|
20
|
-
security: [{ "apiKey": [] }],
|
|
21
|
-
query: {
|
|
22
|
-
limit: params?.limit,
|
|
23
|
-
cursor: params?.cursor,
|
|
24
|
-
release_id: params?.releaseId,
|
|
25
|
-
},
|
|
26
|
-
errors: {
|
|
27
|
-
"400": BadRequestError,
|
|
28
|
-
"401": UnauthorizedError,
|
|
29
|
-
"403": ForbiddenError,
|
|
30
|
-
"404": NotFoundError,
|
|
31
|
-
"429": RateLimitedError,
|
|
32
|
-
"500": InternalServerError,
|
|
33
|
-
},
|
|
34
|
-
idempotent: true,
|
|
35
|
-
schemaKey: "publications.list",
|
|
36
|
-
options,
|
|
37
|
-
}, {
|
|
38
|
-
style: "cursor",
|
|
39
|
-
itemsField: "data",
|
|
40
|
-
cursorParam: "cursor",
|
|
41
|
-
nextCursorField: "next_cursor",
|
|
42
|
-
hasMoreField: "has_more",
|
|
43
|
-
limitParam: "limit",
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Get publishing status
|
|
48
|
-
*
|
|
49
|
-
* Returns the registry publishing status for a release. A status in another organization returns
|
|
50
|
-
* 404 resource_not_found.
|
|
51
|
-
* `GET /publications/{publication_id}`
|
|
52
|
-
*/
|
|
53
|
-
async get(publicationId, options) {
|
|
54
|
-
return this._core.requestData({
|
|
55
|
-
method: "GET",
|
|
56
|
-
path: `/publications/${encodeURIComponent(String(publicationId))}`,
|
|
57
|
-
security: [{ "apiKey": [] }],
|
|
58
|
-
errors: {
|
|
59
|
-
"401": UnauthorizedError,
|
|
60
|
-
"403": ForbiddenError,
|
|
61
|
-
"404": NotFoundError,
|
|
62
|
-
"429": RateLimitedError,
|
|
63
|
-
"500": InternalServerError,
|
|
64
|
-
},
|
|
65
|
-
idempotent: true,
|
|
66
|
-
schemaKey: "publications.get",
|
|
67
|
-
options,
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
}
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { openSync, readSync, closeSync, fstatSync, constants } from "node:fs";
|
|
2
|
-
import { oauthJsonRequest } from "./oauth-request.js";
|
|
3
|
-
import { sameConsoleLoginConfiguration, matchesConsoleBrowserEvidence, type ConsoleLoginCheck, type ConsoleLoginConfiguration } from "./console-login-contract.js";
|
|
4
|
-
import { type OAuthLoginSession } from "./oauth-login.js";
|
|
5
|
-
import { parseNamedCredentials, type CredentialSchemes, type NamedCredentials } from "./named-credentials.js";
|
|
6
|
-
|
|
7
|
-
function readCheck(path: string): ConsoleLoginCheck {
|
|
8
|
-
let fd: number | undefined;
|
|
9
|
-
try {
|
|
10
|
-
fd = openSync(path, constants.O_RDONLY | constants.O_NONBLOCK);
|
|
11
|
-
if (!fstatSync(fd).isFile()) throw new Error();
|
|
12
|
-
const buffer = Buffer.alloc(65_537);
|
|
13
|
-
let size = 0;
|
|
14
|
-
while (size < buffer.length) { const n = readSync(fd, buffer, size, buffer.length - size, null); if (!n) break; size += n; }
|
|
15
|
-
if (size > 65_536) throw new Error();
|
|
16
|
-
const value = JSON.parse(buffer.subarray(0, size).toString("utf8")) as ConsoleLoginCheck;
|
|
17
|
-
if (value.version !== 1 || typeof value.ticket !== "string" || !/^[A-Za-z0-9_-]{43}$/.test(value.ticket) || !value.configuration || !Array.isArray(value.expectations) || !value.expectations.length || value.expectations.length > 3) throw new Error();
|
|
18
|
-
const endpoint = new URL(value.endpoint);
|
|
19
|
-
const development = endpoint.protocol === "http:" && ["127.0.0.1", "[::1]"].includes(endpoint.hostname);
|
|
20
|
-
if (!(endpoint.origin === "https://typeship.dev" || development) || endpoint.pathname !== "/api/authentication/browser" || endpoint.username || endpoint.password || endpoint.search || endpoint.hash) throw new Error();
|
|
21
|
-
const remaining = Date.parse(value.expiresAt) - Date.now();
|
|
22
|
-
if (!Number.isFinite(remaining) || remaining <= 0 || remaining > 600_000) throw new Error();
|
|
23
|
-
return value;
|
|
24
|
-
} catch { throw new Error("Download a new login check from your Typeship Console and pass its JSON file to --console-check. Checks expire after ten minutes."); }
|
|
25
|
-
finally { if (fd !== undefined) closeSync(fd); }
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
/** No traffic to Typeship occurs without the explicit --console-check action.
|
|
29
|
-
* Only the credentials selected for the identity read leave this process;
|
|
30
|
-
* refresh tokens and other stored logins are never sent to the Console. */
|
|
31
|
-
export async function checkConsoleBrowserLogin(input: {
|
|
32
|
-
file: string;
|
|
33
|
-
configuration: ConsoleLoginConfiguration;
|
|
34
|
-
schemes: CredentialSchemes;
|
|
35
|
-
credentials: NamedCredentials;
|
|
36
|
-
login(timeoutMs: number): Promise<OAuthLoginSession>;
|
|
37
|
-
verify(credentials: NamedCredentials, expectations: ConsoleLoginCheck["expectations"]): Promise<void>;
|
|
38
|
-
progress(message: string): void;
|
|
39
|
-
}): Promise<{ ok: true; method: "oauth_browser"; console_verified: true; revoked: boolean | null }> {
|
|
40
|
-
const check = readCheck(input.file);
|
|
41
|
-
if (!sameConsoleLoginConfiguration(input.configuration, check.configuration)) throw new Error("This CLI's authentication settings do not match the saved Target. Regenerate the CLI, select the matching environment, and download a new check.");
|
|
42
|
-
const send = async (body: Record<string, unknown>, timeoutMs = 30_000) => {
|
|
43
|
-
const response = await oauthJsonRequest(check.endpoint, { method: "POST", headers: { "Content-Type": "application/json", Accept: "application/json" }, body: JSON.stringify({ ticket: check.ticket, ...body }) }, timeoutMs);
|
|
44
|
-
if (response.status === 422) throw new Error("Typeship could not verify this login. Check the expected identity, API permissions and saved Target settings, then download a new check.");
|
|
45
|
-
if (response.status !== 200 || response.data?.ok !== true) throw new Error("The Console check expired, was already used, changed, or could not be completed. Download a new check and try again.");
|
|
46
|
-
return response.data;
|
|
47
|
-
};
|
|
48
|
-
await send({ action: "inspect" });
|
|
49
|
-
let revoked: boolean | null = null;
|
|
50
|
-
try {
|
|
51
|
-
const supplied = parseNamedCredentials(input.credentials, input.schemes);
|
|
52
|
-
// Only a complete alternative that uses the fresh browser token proves
|
|
53
|
-
// browser access. An unrelated key-only alternative is not sufficient.
|
|
54
|
-
const requirement = input.configuration.requirements.find((entry) => {
|
|
55
|
-
const names = Object.keys(entry);
|
|
56
|
-
if (!names.some((name) => input.schemes[name]?.kind === "bearer") || !names.every((name) => input.schemes[name]?.kind === "bearer" || supplied[name] !== undefined)) return false;
|
|
57
|
-
const selected = input.configuration.requirements.find((candidate) => Object.keys(candidate).every((name) => names.includes(name)));
|
|
58
|
-
return selected && Object.keys(selected).some((name) => input.schemes[name]?.kind === "bearer");
|
|
59
|
-
});
|
|
60
|
-
if (!requirement) throw new Error("Supply the additional named credentials required by the identity read with --credentials @file or environment variables.");
|
|
61
|
-
input.progress("This check runs a temporary browser login. Typeship will receive only the access token and any additional credentials required for the identity read; refresh tokens stay on this computer.");
|
|
62
|
-
const session = await input.login(Math.max(1, Date.parse(check.expiresAt) - Date.now()));
|
|
63
|
-
try {
|
|
64
|
-
const evidence = { method: "oauth_browser" as const, issuer: session.issuer, clientId: session.clientId, redirectUri: session.redirectUri };
|
|
65
|
-
if (!matchesConsoleBrowserEvidence(input.configuration, evidence)) throw new Error("The browser login did not use the Target's client registration and native callback.");
|
|
66
|
-
const credentials: NamedCredentials = Object.fromEntries(Object.keys(requirement).map((name) => [name, input.schemes[name]!.kind === "bearer" ? session.accessToken : supplied[name]! ]));
|
|
67
|
-
await input.verify(credentials, check.expectations);
|
|
68
|
-
await send({ action: "complete", configuration: input.configuration, evidence, credentials, expectations: check.expectations });
|
|
69
|
-
} finally {
|
|
70
|
-
// Verification sessions never replace the customer's saved login.
|
|
71
|
-
// Revoke the temporary grant when the provider advertises an endpoint.
|
|
72
|
-
if (session.revocationUrl) {
|
|
73
|
-
try {
|
|
74
|
-
const response = await fetch(session.revocationUrl, { method: "POST", redirect: "error", credentials: "omit", signal: AbortSignal.timeout(10_000), headers: { "Content-Type": "application/x-www-form-urlencoded" }, body: new URLSearchParams({ token: session.refreshToken ?? session.accessToken, token_type_hint: session.refreshToken ? "refresh_token" : "access_token", client_id: session.clientId }) });
|
|
75
|
-
void response.body?.cancel().catch(() => {});
|
|
76
|
-
revoked = response.status === 200;
|
|
77
|
-
} catch { revoked = false; }
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
} catch (error) {
|
|
81
|
-
// Report only that the attempt ended. Never send provider errors, identity
|
|
82
|
-
// values or credentials, and never replace the original local error. A
|
|
83
|
-
// consumed check rejects this report, preserving any completed API proof.
|
|
84
|
-
try { await send({ action: "fail" }, 5_000); } catch { /* Best effort; the Console can still expire the check. */ }
|
|
85
|
-
throw error;
|
|
86
|
-
}
|
|
87
|
-
return { ok: true, method: "oauth_browser", console_verified: true, revoked };
|
|
88
|
-
}
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
export interface ConsoleLoginConfiguration {
|
|
3
|
-
baseUrl: string;
|
|
4
|
-
environment: string | null;
|
|
5
|
-
operation: string;
|
|
6
|
-
request: { method: string; path: string; graphqlField: string | null; graphqlQuery: string | null };
|
|
7
|
-
requirements: Record<string, string[]>[];
|
|
8
|
-
issuer: string;
|
|
9
|
-
clientId: string;
|
|
10
|
-
discoveryUrl: string | null;
|
|
11
|
-
authorizationUrl: string | null;
|
|
12
|
-
tokenUrl: string | null;
|
|
13
|
-
redirectUri: string;
|
|
14
|
-
scopes: string[];
|
|
15
|
-
audience: string | null;
|
|
16
|
-
resource: string | null;
|
|
17
|
-
}
|
|
18
|
-
export interface ConsoleIdentityExpectation {
|
|
19
|
-
kind: "account" | "organization" | "user";
|
|
20
|
-
pointer: string;
|
|
21
|
-
expected: string | number;
|
|
22
|
-
}
|
|
23
|
-
export interface ConsoleLoginCheck {
|
|
24
|
-
version: 1;
|
|
25
|
-
endpoint: string;
|
|
26
|
-
ticket: string;
|
|
27
|
-
expiresAt: string;
|
|
28
|
-
configuration: ConsoleLoginConfiguration;
|
|
29
|
-
expectations: ConsoleIdentityExpectation[];
|
|
30
|
-
}
|
|
31
|
-
export interface ConsoleBrowserEvidence {
|
|
32
|
-
method: "oauth_browser";
|
|
33
|
-
issuer: string;
|
|
34
|
-
clientId: string;
|
|
35
|
-
redirectUri: string;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function canonical(value: unknown): string {
|
|
39
|
-
if (Array.isArray(value)) return "[" + value.map(canonical).join(",") + "]";
|
|
40
|
-
if (value && typeof value === "object") return "{" + Object.entries(value).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, item]) => JSON.stringify(key) + ":" + canonical(item)).join(",") + "}";
|
|
41
|
-
return JSON.stringify(value) ?? "null";
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/** Compare the generated product's own settings with the reviewed check.
|
|
45
|
-
* The downloaded file never supplies the CLI's OAuth or API destination. */
|
|
46
|
-
export function sameConsoleLoginConfiguration(left: ConsoleLoginConfiguration, right: ConsoleLoginConfiguration): boolean {
|
|
47
|
-
const normalize = (value: ConsoleLoginConfiguration) => ({ ...value,
|
|
48
|
-
baseUrl: new URL(value.baseUrl).href,
|
|
49
|
-
scopes: [...new Set(value.scopes)].sort(),
|
|
50
|
-
requirements: value.requirements.map((entry) => Object.fromEntries(Object.entries(entry).map(([key, scopes]) => [key, [...new Set(scopes)].sort()]))),
|
|
51
|
-
});
|
|
52
|
-
try { return canonical(normalize(left)) === canonical(normalize(right)); } catch { return false; }
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
export function matchesConsoleBrowserEvidence(config: ConsoleLoginConfiguration, evidence: ConsoleBrowserEvidence): boolean {
|
|
56
|
-
try {
|
|
57
|
-
if (evidence.method !== "oauth_browser" || evidence.issuer !== config.issuer || evidence.clientId !== config.clientId) return false;
|
|
58
|
-
const configured = new URL(config.redirectUri), actual = new URL(evidence.redirectUri);
|
|
59
|
-
if (configured.protocol !== "http:" || !["127.0.0.1", "[::1]"].includes(configured.hostname) || configured.username || configured.password || configured.search || configured.hash) return false;
|
|
60
|
-
if (configured.port && configured.port !== actual.port) return false;
|
|
61
|
-
if (!actual.port) return false;
|
|
62
|
-
configured.port = actual.port;
|
|
63
|
-
return configured.href === actual.href;
|
|
64
|
-
} catch { return false; }
|
|
65
|
-
}
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
// typeship — publications resource.
|
|
2
|
-
// Generated by typeship — https://typeship.dev
|
|
3
|
-
|
|
4
|
-
import { HttpCore, type RequestOptions } from "../core/http.js";
|
|
5
|
-
import { paginate, PagePromise } from "../core/pagination.js";
|
|
6
|
-
import {
|
|
7
|
-
ResponseParseError,
|
|
8
|
-
TransportError,
|
|
9
|
-
UnexpectedApiError,
|
|
10
|
-
ValidationError,
|
|
11
|
-
BadRequestError,
|
|
12
|
-
ForbiddenError,
|
|
13
|
-
InternalServerError,
|
|
14
|
-
NotFoundError,
|
|
15
|
-
RateLimitedError,
|
|
16
|
-
UnauthorizedError,
|
|
17
|
-
} from "../errors.js";
|
|
18
|
-
import type {
|
|
19
|
-
Publication,
|
|
20
|
-
PublicationId,
|
|
21
|
-
PublicationList,
|
|
22
|
-
PublicationListRead,
|
|
23
|
-
PublicationRead,
|
|
24
|
-
PublicationResponse,
|
|
25
|
-
PublicationResponseRead,
|
|
26
|
-
ReleaseId,
|
|
27
|
-
} from "../types.js";
|
|
28
|
-
|
|
29
|
-
export class PublicationsResource {
|
|
30
|
-
constructor(private readonly _core: HttpCore) {}
|
|
31
|
-
/**
|
|
32
|
-
* List publications
|
|
33
|
-
*
|
|
34
|
-
* Auto-paginates: `for await (const item of …)` walks every page.
|
|
35
|
-
* `GET /publications`
|
|
36
|
-
*/
|
|
37
|
-
list(
|
|
38
|
-
params?: PublicationsListParams,
|
|
39
|
-
options?: RequestOptions,
|
|
40
|
-
): PagePromise<PublicationRead, PublicationsListError> {
|
|
41
|
-
return paginate<PublicationRead, PublicationsListError>(this._core, {
|
|
42
|
-
method: "GET",
|
|
43
|
-
path: "/publications",
|
|
44
|
-
security: [{"apiKey":[]}],
|
|
45
|
-
query: {
|
|
46
|
-
limit: params?.limit,
|
|
47
|
-
cursor: params?.cursor,
|
|
48
|
-
release_id: params?.releaseId,
|
|
49
|
-
},
|
|
50
|
-
errors: {
|
|
51
|
-
"400": BadRequestError,
|
|
52
|
-
"401": UnauthorizedError,
|
|
53
|
-
"403": ForbiddenError,
|
|
54
|
-
"404": NotFoundError,
|
|
55
|
-
"429": RateLimitedError,
|
|
56
|
-
"500": InternalServerError,
|
|
57
|
-
},
|
|
58
|
-
idempotent: true,
|
|
59
|
-
schemaKey: "publications.list",
|
|
60
|
-
options,
|
|
61
|
-
}, {
|
|
62
|
-
style: "cursor",
|
|
63
|
-
itemsField: "data",
|
|
64
|
-
cursorParam: "cursor",
|
|
65
|
-
nextCursorField: "next_cursor",
|
|
66
|
-
hasMoreField: "has_more",
|
|
67
|
-
limitParam: "limit",
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
/**
|
|
72
|
-
* Get publishing status
|
|
73
|
-
*
|
|
74
|
-
* Returns the registry publishing status for a release. A status in another organization returns
|
|
75
|
-
* 404 resource_not_found.
|
|
76
|
-
* `GET /publications/{publication_id}`
|
|
77
|
-
*/
|
|
78
|
-
async get(publicationId: PublicationId, options?: RequestOptions): Promise<PublicationResponseRead> {
|
|
79
|
-
return this._core.requestData<PublicationResponseRead, PublicationsGetError>({
|
|
80
|
-
method: "GET",
|
|
81
|
-
path: `/publications/${encodeURIComponent(String(publicationId))}`,
|
|
82
|
-
security: [{"apiKey":[]}],
|
|
83
|
-
errors: {
|
|
84
|
-
"401": UnauthorizedError,
|
|
85
|
-
"403": ForbiddenError,
|
|
86
|
-
"404": NotFoundError,
|
|
87
|
-
"429": RateLimitedError,
|
|
88
|
-
"500": InternalServerError,
|
|
89
|
-
},
|
|
90
|
-
idempotent: true,
|
|
91
|
-
schemaKey: "publications.get",
|
|
92
|
-
options,
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
export interface PublicationsListParams {
|
|
98
|
-
/**
|
|
99
|
-
* Maximum number of resources to return. Omit for 20; otherwise supply base-10 digits
|
|
100
|
-
* representing an integer from 1 to 100. Empty, malformed, or out-of-range values return 400
|
|
101
|
-
* input_invalid. List query parameters must appear only once; repeated or unrecognized parameters
|
|
102
|
-
* return 400 query_param_invalid.
|
|
103
|
-
*/
|
|
104
|
-
limit?: number;
|
|
105
|
-
/**
|
|
106
|
-
* Opaque cursor from the preceding page's next_cursor. Valid only for the same organization,
|
|
107
|
-
* operation, filters, and ordering that issued it. Omit to start at the first page. Empty or
|
|
108
|
-
* malformed cursors, and cursors issued for different filters, return 400 cursor_invalid; start
|
|
109
|
-
* again from the first page. Repeated cursors return 400 query_param_invalid. The page limit may
|
|
110
|
-
* change between requests.
|
|
111
|
-
*/
|
|
112
|
-
cursor?: string;
|
|
113
|
-
/** Only publications of this release. */
|
|
114
|
-
releaseId?: ReleaseId;
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
/** Typed errors `list` can throw. */
|
|
118
|
-
export type PublicationsListError =
|
|
119
|
-
| BadRequestError
|
|
120
|
-
| UnauthorizedError
|
|
121
|
-
| ForbiddenError
|
|
122
|
-
| NotFoundError
|
|
123
|
-
| RateLimitedError
|
|
124
|
-
| InternalServerError
|
|
125
|
-
| UnexpectedApiError
|
|
126
|
-
| ResponseParseError
|
|
127
|
-
| TransportError
|
|
128
|
-
| ValidationError;
|
|
129
|
-
|
|
130
|
-
/** Typed errors `get` can throw. */
|
|
131
|
-
export type PublicationsGetError =
|
|
132
|
-
| UnauthorizedError
|
|
133
|
-
| ForbiddenError
|
|
134
|
-
| NotFoundError
|
|
135
|
-
| RateLimitedError
|
|
136
|
-
| InternalServerError
|
|
137
|
-
| UnexpectedApiError
|
|
138
|
-
| ResponseParseError
|
|
139
|
-
| TransportError
|
|
140
|
-
| ValidationError;
|