@zuplo/cli 6.59.28 → 6.59.29
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cmds/login.d.ts.map +1 -1
- package/dist/cmds/login.js +1 -1
- package/dist/cmds/login.js.map +1 -1
- package/dist/common/constants.d.ts +1 -1
- package/dist/common/constants.d.ts.map +1 -1
- package/dist/common/constants.js +1 -1
- package/dist/common/constants.js.map +1 -1
- package/dist/login/login.d.ts +1 -10
- package/dist/login/login.d.ts.map +1 -1
- package/dist/login/login.js +142 -75
- package/dist/login/login.js.map +1 -1
- package/dist/login/tokens.d.ts.map +1 -1
- package/dist/login/tokens.js +24 -1
- package/dist/login/tokens.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +4 -4
- package/dist/login/html.d.ts +0 -3
- package/dist/login/html.d.ts.map +0 -1
- package/dist/login/html.js +0 -162
- package/dist/login/html.js.map +0 -1
- package/dist/login/server.d.ts +0 -4
- package/dist/login/server.d.ts.map +0 -1
- package/dist/login/server.js +0 -37
- package/dist/login/server.js.map +0 -1
package/dist/cmds/login.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/cmds/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;;qBAcV,IAAI,KAAG,IAAI,CAAC,OAAO,CAAC;oBAGf,OAAO;;AAT/B,
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/cmds/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC;;;;qBAcV,IAAI,KAAG,IAAI,CAAC,OAAO,CAAC;oBAGf,OAAO;;AAT/B,wBAgBE"}
|
package/dist/cmds/login.js
CHANGED
|
@@ -11,7 +11,7 @@ export default {
|
|
|
11
11
|
handler: async (argv) => {
|
|
12
12
|
await captureEvent({ argv, event: "zuplo login" });
|
|
13
13
|
await login();
|
|
14
|
-
await printResultToConsoleAndExitGracefully("
|
|
14
|
+
await printResultToConsoleAndExitGracefully("\nSuccessfully authenticated.");
|
|
15
15
|
},
|
|
16
16
|
};
|
|
17
17
|
//# sourceMappingURL=login.js.map
|
package/dist/cmds/login.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/cmds/login.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,6CAA6C,CAAC;AACvE,OAAO,WAAW,EAAE,EAClB,qCAAqC,GACtC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,eAAe;IAEb,IAAI,EAAE,KAAK;IAEX,OAAO,EAAE,OAAO;IAEhB,OAAO,EAAE,CAAC,KAAW,EAAiB,EAAE;QACtC,OAAO,KAAK,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;QAC/B,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;QACnD,MAAM,KAAK,EAAE,CAAC;QACd,MAAM,qCAAqC,
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/cmds/login.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,4BAA4B,CAAC;AAC1D,OAAO,EAAE,QAAQ,EAAE,MAAM,6CAA6C,CAAC;AACvE,OAAO,WAAW,EAAE,EAClB,qCAAqC,GACtC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAE1C,eAAe;IAEb,IAAI,EAAE,KAAK;IAEX,OAAO,EAAE,OAAO;IAEhB,OAAO,EAAE,CAAC,KAAW,EAAiB,EAAE;QACtC,OAAO,KAAK,CAAC,UAAU,CAAC,CAAC,WAAW,EAAE,QAAQ,CAAC,CAAC,CAAC;IACnD,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,IAAa,EAAE,EAAE;QAC/B,MAAM,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,aAAa,EAAE,CAAC,CAAC;QACnD,MAAM,KAAK,EAAE,CAAC;QACd,MAAM,qCAAqC,CACzC,+BAA+B,CAChC,CAAC;IACJ,CAAC;CACF,CAAC","sourcesContent":["import { Argv } from \"yargs\";\nimport { captureEvent } from \"../common/analytics/lib.js\";\nimport { identify } from \"../common/middleware/user-identification.js\";\nimport setBlocking, {\n printResultToConsoleAndExitGracefully,\n} from \"../common/output.js\";\nimport { login } from \"../login/login.js\";\n\nexport default {\n // For now, hide this command\n desc: false,\n // desc: \"Authenticates the user\",\n command: \"login\",\n\n builder: (yargs: Argv): Argv<unknown> => {\n return yargs.middleware([setBlocking, identify]);\n },\n handler: async (argv: unknown) => {\n await captureEvent({ argv, event: \"zuplo login\" });\n await login();\n await printResultToConsoleAndExitGracefully(\n \"\\nSuccessfully authenticated.\"\n );\n },\n};\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export declare const ZUPLO_PREFERRED_JSON_FILE = "zuplo.jsonc";
|
|
2
2
|
export declare const ZUPLO_FALLBACK_JSON_FILE = "zuplo.json";
|
|
3
|
-
export declare const ZUPLO_CLI_XDG_FOLDER_NAME = "
|
|
3
|
+
export declare const ZUPLO_CLI_XDG_FOLDER_NAME = "zuplo";
|
|
4
4
|
export declare const ZUPLO_AUTH_FILE_NAME = "auth.json";
|
|
5
5
|
export declare const ZUPLO_VERSION_CHECK_FILE = "version.json";
|
|
6
6
|
export declare const ZUPLO_SYSTEM_ENV_VAR = ".env.zuplo";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/common/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,yBAAyB,gBAAgB,CAAC;AACvD,eAAO,MAAM,wBAAwB,eAAe,CAAC;AACrD,eAAO,MAAM,yBAAyB,
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/common/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,yBAAyB,gBAAgB,CAAC;AACvD,eAAO,MAAM,wBAAwB,eAAe,CAAC;AACrD,eAAO,MAAM,yBAAyB,UAAU,CAAC;AACjD,eAAO,MAAM,oBAAoB,cAAc,CAAC;AAChD,eAAO,MAAM,wBAAwB,iBAAiB,CAAC;AACvD,eAAO,MAAM,oBAAoB,eAAe,CAAC;AAGjD,eAAO,MAAM,sBAAsB,kBAAkB,CAAC;AACtD,eAAO,MAAM,eAAe,IAAI,CAAC;AACjC,eAAO,MAAM,sBAAsB,KAAK,CAAC;AAGzC,eAAO,MAAM,sBAAsB,kBAAkB,CAAC;AAItD,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC,eAAO,MAAM,eAAe,qBAAqB,CAAC;AAGlD,eAAO,MAAM,UAAU,wFACgE,CAAC;AACxF,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAG7C,eAAO,MAAM,oBAAoB,oDACkB,CAAC"}
|
package/dist/common/constants.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export const ZUPLO_PREFERRED_JSON_FILE = "zuplo.jsonc";
|
|
2
2
|
export const ZUPLO_FALLBACK_JSON_FILE = "zuplo.json";
|
|
3
|
-
export const ZUPLO_CLI_XDG_FOLDER_NAME = "
|
|
3
|
+
export const ZUPLO_CLI_XDG_FOLDER_NAME = "zuplo";
|
|
4
4
|
export const ZUPLO_AUTH_FILE_NAME = "auth.json";
|
|
5
5
|
export const ZUPLO_VERSION_CHECK_FILE = "version.json";
|
|
6
6
|
export const ZUPLO_SYSTEM_ENV_VAR = ".env.zuplo";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/common/constants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,yBAAyB,GAAG,aAAa,CAAC;AACvD,MAAM,CAAC,MAAM,wBAAwB,GAAG,YAAY,CAAC;AACrD,MAAM,CAAC,MAAM,yBAAyB,GAAG,
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/common/constants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,yBAAyB,GAAG,aAAa,CAAC;AACvD,MAAM,CAAC,MAAM,wBAAwB,GAAG,YAAY,CAAC;AACrD,MAAM,CAAC,MAAM,yBAAyB,GAAG,OAAO,CAAC;AACjD,MAAM,CAAC,MAAM,oBAAoB,GAAG,WAAW,CAAC;AAChD,MAAM,CAAC,MAAM,wBAAwB,GAAG,cAAc,CAAC;AACvD,MAAM,CAAC,MAAM,oBAAoB,GAAG,YAAY,CAAC;AAGjD,MAAM,CAAC,MAAM,sBAAsB,GAAG,eAAe,CAAC;AACtD,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC;AACjC,MAAM,CAAC,MAAM,sBAAsB,GAAG,EAAE,CAAC;AAGzC,MAAM,CAAC,MAAM,sBAAsB,GAAG,eAAe,CAAC;AAItD,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AAEtC,MAAM,CAAC,MAAM,eAAe,GAAG,kBAAkB,CAAC;AAGlD,MAAM,CAAC,MAAM,UAAU,GACrB,qFAAqF,CAAC;AACxF,MAAM,CAAC,MAAM,wBAAwB,GAAG,IAAI,CAAC;AAG7C,MAAM,CAAC,MAAM,oBAAoB,GAC/B,iDAAiD,CAAC","sourcesContent":["// Configuration\n\nexport const ZUPLO_PREFERRED_JSON_FILE = \"zuplo.jsonc\";\nexport const ZUPLO_FALLBACK_JSON_FILE = \"zuplo.json\";\nexport const ZUPLO_CLI_XDG_FOLDER_NAME = \"zuplo\";\nexport const ZUPLO_AUTH_FILE_NAME = \"auth.json\";\nexport const ZUPLO_VERSION_CHECK_FILE = \"version.json\";\nexport const ZUPLO_SYSTEM_ENV_VAR = \".env.zuplo\";\n\n// Deployer\nexport const DEPLOYER_METADATA_FILE = \"deployer.json\";\nexport const MAX_HASH_LENGTH = 7;\nexport const MAX_PRETTY_BRANCH_NAME = 10;\n\n// Special keys\nexport const ZUPLO_USER_ID_ARGV_KEY = \"zuplo-user-id\";\n\n// Test\n// Where are the tests located (recursively)\nexport const TEST_IN_FOLDER = \"tests\";\n// Where should we generate the tests\nexport const TEST_OUT_FOLDER = \".zuplo/__tests__\";\n\n// Sentry\nexport const SENTRY_DSN =\n \"https://28220fd3185a1281daff09ade2114dca@o1036703.ingest.sentry.io/4505880249040896\";\nexport const MAX_WAIT_PENDING_TIME_MS = 1000;\n\n// PostHog\nexport const POST_HOG_CAPTURE_KEY =\n \"phc_LDSwSTOvIjiDDZql2g54Q7xEXoQ0EN9RMYb3STbdz1V\";\n"]}
|
package/dist/login/login.d.ts
CHANGED
|
@@ -1,15 +1,6 @@
|
|
|
1
|
-
export declare const AUTH_SERVER_PORT = 57801;
|
|
2
1
|
export declare const CLIENT_ID = "mYLGcH7kB4P0pw0HAk6GH7raRwYhSlW4";
|
|
3
|
-
export declare const CALLBACK_URL = "http://localhost:57801/";
|
|
4
2
|
export declare const AUTH0_DOMAIN = "auth.zuplo.com";
|
|
5
|
-
export declare const OAUTH_SCOPE = "
|
|
3
|
+
export declare const OAUTH_SCOPE = "offline_access";
|
|
6
4
|
export declare const OAUTH_AUDIENCE = "https://dev.zuplo.com/";
|
|
7
|
-
export declare const encode: (value: string) => string;
|
|
8
|
-
export declare const decode: (value: string) => string;
|
|
9
|
-
export declare const createRandomString: () => string;
|
|
10
|
-
export declare const bufferToBase64UrlEncoded: (
|
|
11
|
-
input: number[] | Uint8Array
|
|
12
|
-
) => string;
|
|
13
|
-
export declare const sha256: (s: string) => Promise<any>;
|
|
14
5
|
export declare function login(): Promise<void>;
|
|
15
6
|
//# sourceMappingURL=login.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/login/login.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../src/login/login.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,SAAS,qCAAqC,CAAC;AAC5D,eAAO,MAAM,YAAY,mBAAmB,CAAC;AAC7C,eAAO,MAAM,WAAW,mBAAmB,CAAC;AAC5C,eAAO,MAAM,cAAc,2BAA2B,CAAC;AAgLvD,wBAAsB,KAAK,kBAqD1B"}
|
package/dist/login/login.js
CHANGED
|
@@ -1,93 +1,160 @@
|
|
|
1
|
-
import
|
|
2
|
-
import {
|
|
1
|
+
import opn from "open";
|
|
2
|
+
import { logger } from "../common/logger.js";
|
|
3
3
|
import { saveAuthState } from "./tokens.js";
|
|
4
|
-
|
|
4
|
+
import box from "../common/utils/box.js";
|
|
5
|
+
import { printCriticalFailureToConsoleAndExit } from "../common/output.js";
|
|
5
6
|
export const CLIENT_ID = "mYLGcH7kB4P0pw0HAk6GH7raRwYhSlW4";
|
|
6
|
-
export const CALLBACK_URL = `http://localhost:${AUTH_SERVER_PORT}/`;
|
|
7
7
|
export const AUTH0_DOMAIN = "auth.zuplo.com";
|
|
8
|
-
export const OAUTH_SCOPE = "
|
|
8
|
+
export const OAUTH_SCOPE = "offline_access";
|
|
9
9
|
export const OAUTH_AUDIENCE = "https://dev.zuplo.com/";
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
31
|
-
export async function login() {
|
|
32
|
-
const code_verifier = createRandomString();
|
|
33
|
-
const code_challengeBuffer = await sha256(code_verifier);
|
|
34
|
-
const code_challenge = bufferToBase64UrlEncoded(code_challengeBuffer);
|
|
35
|
-
const authUrl = new URL(`https://${AUTH0_DOMAIN}/authorize`);
|
|
36
|
-
authUrl.searchParams.set("response_type", "code");
|
|
37
|
-
authUrl.searchParams.set("code_challenge", code_challenge);
|
|
38
|
-
authUrl.searchParams.set("code_challenge_method", "S256");
|
|
39
|
-
authUrl.searchParams.set("client_id", CLIENT_ID);
|
|
40
|
-
authUrl.searchParams.set("redirect_uri", CALLBACK_URL);
|
|
41
|
-
authUrl.searchParams.set("scope", OAUTH_SCOPE);
|
|
42
|
-
authUrl.searchParams.set("audience", OAUTH_AUDIENCE);
|
|
43
|
-
const params = await browserAuth(authUrl.toString());
|
|
44
|
-
const error = params.get("error");
|
|
45
|
-
if (error) {
|
|
46
|
-
const errorDescription = params.get("error_description");
|
|
47
|
-
const errorUri = params.get("error_uri");
|
|
10
|
+
class OAuthError extends Error {
|
|
11
|
+
}
|
|
12
|
+
async function initiateDeviceFlow() {
|
|
13
|
+
const response = await fetch(`https://${AUTH0_DOMAIN}/oauth/device/code`, {
|
|
14
|
+
method: "POST",
|
|
15
|
+
headers: {
|
|
16
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
17
|
+
},
|
|
18
|
+
body: new URLSearchParams({
|
|
19
|
+
client_id: CLIENT_ID,
|
|
20
|
+
scope: OAUTH_SCOPE,
|
|
21
|
+
audience: OAUTH_AUDIENCE,
|
|
22
|
+
}),
|
|
23
|
+
});
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
let errorDetails = {};
|
|
26
|
+
try {
|
|
27
|
+
errorDetails = await response.json();
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
}
|
|
48
31
|
const Sentry = await import("@sentry/node");
|
|
49
|
-
|
|
32
|
+
const errorMessage = errorDetails.error_description ||
|
|
33
|
+
errorDetails.error ||
|
|
34
|
+
response.statusText;
|
|
35
|
+
Sentry.captureException(new Error(`Failed to initiate device flow: ${errorMessage}`), {
|
|
50
36
|
tags: {
|
|
51
|
-
oauth_error: error,
|
|
52
|
-
source: "
|
|
37
|
+
oauth_error: errorDetails.error || "device_code_failed",
|
|
38
|
+
source: "cli_device_flow_init",
|
|
39
|
+
status_code: response.status,
|
|
53
40
|
},
|
|
54
41
|
extra: {
|
|
55
|
-
error_description:
|
|
56
|
-
|
|
57
|
-
|
|
42
|
+
error_description: errorDetails.error_description,
|
|
43
|
+
error_details: errorDetails,
|
|
44
|
+
status: response.status,
|
|
45
|
+
status_text: response.statusText,
|
|
58
46
|
},
|
|
59
47
|
});
|
|
60
|
-
throw new Error(
|
|
48
|
+
throw new Error(`Failed to initiate device flow: ${errorMessage}`);
|
|
61
49
|
}
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
50
|
+
return response.json();
|
|
51
|
+
}
|
|
52
|
+
async function pollForToken(deviceCode, interval, expiresIn) {
|
|
53
|
+
const startTime = Date.now();
|
|
54
|
+
const expirationTime = startTime + expiresIn * 1000;
|
|
55
|
+
while (Date.now() < expirationTime) {
|
|
56
|
+
await new Promise((resolve) => setTimeout(resolve, interval * 1000));
|
|
57
|
+
const response = await fetch(`https://${AUTH0_DOMAIN}/oauth/token`, {
|
|
58
|
+
method: "POST",
|
|
59
|
+
headers: {
|
|
60
|
+
"Content-Type": "application/x-www-form-urlencoded",
|
|
73
61
|
},
|
|
62
|
+
body: new URLSearchParams({
|
|
63
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
64
|
+
device_code: deviceCode,
|
|
65
|
+
client_id: CLIENT_ID,
|
|
66
|
+
}),
|
|
74
67
|
});
|
|
75
|
-
|
|
68
|
+
const result = await response.json();
|
|
69
|
+
if (result.error) {
|
|
70
|
+
if (result.error === "authorization_pending") {
|
|
71
|
+
logger.debug("Authorization pending, continuing to poll...");
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
else if (result.error === "slow_down") {
|
|
75
|
+
interval = interval + 5;
|
|
76
|
+
logger.debug(`Slowing down polling interval to ${interval} seconds`);
|
|
77
|
+
continue;
|
|
78
|
+
}
|
|
79
|
+
else if (result.error === "expired_token") {
|
|
80
|
+
const Sentry = await import("@sentry/node");
|
|
81
|
+
Sentry.captureException(new Error("Device code expired before user authorization"), {
|
|
82
|
+
tags: {
|
|
83
|
+
oauth_error: "expired_token",
|
|
84
|
+
source: "cli_device_flow_poll",
|
|
85
|
+
},
|
|
86
|
+
});
|
|
87
|
+
throw new OAuthError("The device code has expired.");
|
|
88
|
+
}
|
|
89
|
+
else if (result.error === "access_denied") {
|
|
90
|
+
const Sentry = await import("@sentry/node");
|
|
91
|
+
Sentry.captureException(new Error("User denied authorization"), {
|
|
92
|
+
tags: {
|
|
93
|
+
oauth_error: "access_denied",
|
|
94
|
+
source: "cli_device_flow_poll",
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
throw new OAuthError("Authorization was denied.");
|
|
98
|
+
}
|
|
99
|
+
else {
|
|
100
|
+
const Sentry = await import("@sentry/node");
|
|
101
|
+
Sentry.captureException(new Error(`Device flow error: ${result.error}`), {
|
|
102
|
+
tags: {
|
|
103
|
+
oauth_error: result.error,
|
|
104
|
+
source: "cli_device_flow_poll",
|
|
105
|
+
},
|
|
106
|
+
extra: {
|
|
107
|
+
error_description: result.error_description,
|
|
108
|
+
},
|
|
109
|
+
});
|
|
110
|
+
throw new OAuthError(result.error_description || `OAuth error: ${result.error}`);
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
if (result.access_token) {
|
|
114
|
+
return result;
|
|
115
|
+
}
|
|
76
116
|
}
|
|
77
|
-
const
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
tokenParams.set("redirect_uri", CALLBACK_URL);
|
|
83
|
-
const response = await fetch(`https://${AUTH0_DOMAIN}/oauth/token`, {
|
|
84
|
-
method: "POST",
|
|
85
|
-
headers: {
|
|
86
|
-
"Content-Type": "application/x-www-form-urlencoded",
|
|
117
|
+
const Sentry = await import("@sentry/node");
|
|
118
|
+
Sentry.captureException(new Error("Device flow timed out waiting for user authorization"), {
|
|
119
|
+
tags: {
|
|
120
|
+
oauth_error: "timeout",
|
|
121
|
+
source: "cli_device_flow_poll",
|
|
87
122
|
},
|
|
88
|
-
body: tokenParams,
|
|
89
123
|
});
|
|
90
|
-
|
|
91
|
-
|
|
124
|
+
throw new OAuthError("Timed out waiting for authorization.");
|
|
125
|
+
}
|
|
126
|
+
export async function login() {
|
|
127
|
+
try {
|
|
128
|
+
const deviceResponse = await initiateDeviceFlow();
|
|
129
|
+
console.log(box(` To login, please visit:
|
|
130
|
+
|
|
131
|
+
${deviceResponse.verification_uri_complete}
|
|
132
|
+
|
|
133
|
+
After completing login in the browser you can close the tab.`, {
|
|
134
|
+
borderColor: "white",
|
|
135
|
+
}));
|
|
136
|
+
try {
|
|
137
|
+
await opn(deviceResponse.verification_uri_complete);
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
}
|
|
141
|
+
let tokenResponse;
|
|
142
|
+
try {
|
|
143
|
+
tokenResponse = await pollForToken(deviceResponse.device_code, deviceResponse.interval, deviceResponse.expires_in);
|
|
144
|
+
}
|
|
145
|
+
catch (err) {
|
|
146
|
+
if (err instanceof OAuthError) {
|
|
147
|
+
return printCriticalFailureToConsoleAndExit(`${err.message}. Please run the login command again.`);
|
|
148
|
+
}
|
|
149
|
+
else {
|
|
150
|
+
return printCriticalFailureToConsoleAndExit("An error occurred while attempting to authenticate. Please run the login command again. If the problem persists, contact support@zuplo.com.");
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
await saveAuthState(tokenResponse);
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
logger.error(error, "Login failed");
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
92
159
|
}
|
|
93
160
|
//# sourceMappingURL=login.js.map
|
package/dist/login/login.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/login/login.ts"],"names":[],"mappings":"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","sourcesContent":["import crypto from \"node:crypto\";\nimport { browserAuth } from \"./server.js\";\nimport { OAuthResponse, saveAuthState } from \"./tokens.js\";\n\nexport const AUTH_SERVER_PORT = 57801;\nexport const CLIENT_ID = \"mYLGcH7kB4P0pw0HAk6GH7raRwYhSlW4\";\nexport const CALLBACK_URL = `http://localhost:${AUTH_SERVER_PORT}/`;\nexport const AUTH0_DOMAIN = \"auth.zuplo.com\";\nexport const OAUTH_SCOPE = \"openid email offline_access\";\nexport const OAUTH_AUDIENCE = \"https://dev.zuplo.com/\";\n\nexport const encode = (value: string) => btoa(value);\nexport const decode = (value: string) => atob(value);\n\nexport const createRandomString = () => {\n const charset =\n \"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_~.\";\n let random = \"\";\n const randomValues = Array.from(crypto.getRandomValues(new Uint8Array(43)));\n randomValues.forEach((v) => (random += charset[v % charset.length]));\n return random;\n};\n\nconst urlEncodeB64 = (input: string) => {\n const b64Chars: { [index: string]: string } = { \"+\": \"-\", \"/\": \"_\", \"=\": \"\" };\n return input.replace(/[+/=]/g, (m: string) => b64Chars[m]);\n};\n\nexport const bufferToBase64UrlEncoded = (input: number[] | Uint8Array) => {\n const ie11SafeInput = new Uint8Array(input);\n return urlEncodeB64(btoa(String.fromCharCode(...Array.from(ie11SafeInput))));\n};\n\nexport const sha256 = async (s: string) => {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const digestOp: any = crypto.subtle.digest(\n { name: \"SHA-256\" },\n new TextEncoder().encode(s)\n );\n\n return await digestOp;\n};\n\nexport async function login() {\n const code_verifier = createRandomString();\n const code_challengeBuffer = await sha256(code_verifier);\n const code_challenge = bufferToBase64UrlEncoded(code_challengeBuffer);\n\n const authUrl = new URL(`https://${AUTH0_DOMAIN}/authorize`);\n\n authUrl.searchParams.set(\"response_type\", \"code\");\n authUrl.searchParams.set(\"code_challenge\", code_challenge);\n authUrl.searchParams.set(\"code_challenge_method\", \"S256\");\n authUrl.searchParams.set(\"client_id\", CLIENT_ID);\n authUrl.searchParams.set(\"redirect_uri\", CALLBACK_URL);\n authUrl.searchParams.set(\"scope\", OAUTH_SCOPE);\n authUrl.searchParams.set(\"audience\", OAUTH_AUDIENCE);\n\n const params = await browserAuth(authUrl.toString());\n\n // Check for OAuth errors first\n const error = params.get(\"error\");\n if (error) {\n const errorDescription = params.get(\"error_description\");\n const errorUri = params.get(\"error_uri\");\n\n // Import Sentry dynamically to capture OAuth errors\n const Sentry = await import(\"@sentry/node\");\n Sentry.captureException(new Error(`OAuth Error: ${error}`), {\n tags: {\n oauth_error: error,\n source: \"cli_login\",\n },\n extra: {\n error_description: errorDescription,\n error_uri: errorUri,\n callback_url: authUrl.toString(),\n },\n });\n\n throw new Error(errorDescription || `OAuth error: ${error}`);\n }\n\n const code = params.get(\"code\");\n if (code === null) {\n // Import Sentry dynamically for unexpected state\n const Sentry = await import(\"@sentry/node\");\n Sentry.captureException(\n new Error(\"OAuth callback received without code or error parameters\"),\n {\n tags: {\n oauth_error: \"missing_parameters\",\n source: \"cli_login\",\n },\n extra: {\n callback_url: authUrl.toString(),\n all_params: Object.fromEntries(params.entries()),\n },\n }\n );\n\n throw new Error(\"Authorization failed: No authorization code received\");\n }\n\n const tokenParams = new URLSearchParams();\n tokenParams.set(\"grant_type\", \"authorization_code\");\n tokenParams.set(\"client_id\", CLIENT_ID);\n tokenParams.set(\"code_verifier\", code_verifier);\n tokenParams.set(\"code\", code);\n tokenParams.set(\"redirect_uri\", CALLBACK_URL);\n\n const response = await fetch(`https://${AUTH0_DOMAIN}/oauth/token`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: tokenParams,\n });\n\n const result: OAuthResponse = await response.json();\n await saveAuthState(result);\n}\n"]}
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/login/login.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,MAAM,CAAC;AACvB,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAiB,aAAa,EAAE,MAAM,aAAa,CAAC;AAC3D,OAAO,GAAG,MAAM,wBAAwB,CAAC;AACzC,OAAO,EAAE,oCAAoC,EAAE,MAAM,qBAAqB,CAAC;AAE3E,MAAM,CAAC,MAAM,SAAS,GAAG,kCAAkC,CAAC;AAC5D,MAAM,CAAC,MAAM,YAAY,GAAG,gBAAgB,CAAC;AAC7C,MAAM,CAAC,MAAM,WAAW,GAAG,gBAAgB,CAAC;AAC5C,MAAM,CAAC,MAAM,cAAc,GAAG,wBAAwB,CAAC;AAgBvD,MAAM,UAAW,SAAQ,KAAK;CAAG;AAKjC,KAAK,UAAU,kBAAkB;IAC/B,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,WAAW,YAAY,oBAAoB,EAAE;QACxE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,mCAAmC;SACpD;QACD,IAAI,EAAE,IAAI,eAAe,CAAC;YACxB,SAAS,EAAE,SAAS;YACpB,KAAK,EAAE,WAAW;YAClB,QAAQ,EAAE,cAAc;SACzB,CAAC;KACH,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QAEjB,IAAI,YAAY,GAAQ,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,YAAY,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QACvC,CAAC;QAAC,MAAM,CAAC;QAET,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;QAC5C,MAAM,YAAY,GAChB,YAAY,CAAC,iBAAiB;YAC9B,YAAY,CAAC,KAAK;YAClB,QAAQ,CAAC,UAAU,CAAC;QAEtB,MAAM,CAAC,gBAAgB,CACrB,IAAI,KAAK,CAAC,mCAAmC,YAAY,EAAE,CAAC,EAC5D;YACE,IAAI,EAAE;gBACJ,WAAW,EAAE,YAAY,CAAC,KAAK,IAAI,oBAAoB;gBACvD,MAAM,EAAE,sBAAsB;gBAC9B,WAAW,EAAE,QAAQ,CAAC,MAAM;aAC7B;YACD,KAAK,EAAE;gBACL,iBAAiB,EAAE,YAAY,CAAC,iBAAiB;gBACjD,aAAa,EAAE,YAAY;gBAC3B,MAAM,EAAE,QAAQ,CAAC,MAAM;gBACvB,WAAW,EAAE,QAAQ,CAAC,UAAU;aACjC;SACF,CACF,CAAC;QAEF,MAAM,IAAI,KAAK,CAAC,mCAAmC,YAAY,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAAE,CAAC;AACzB,CAAC;AAKD,KAAK,UAAU,YAAY,CACzB,UAAkB,EAClB,QAAgB,EAChB,SAAiB;IAEjB,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;IAC7B,MAAM,cAAc,GAAG,SAAS,GAAG,SAAS,GAAG,IAAI,CAAC;IAEpD,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc,EAAE,CAAC;QAEnC,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC;QAErE,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,WAAW,YAAY,cAAc,EAAE;YAClE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,mCAAmC;aACpD;YACD,IAAI,EAAE,IAAI,eAAe,CAAC;gBACxB,UAAU,EAAE,8CAA8C;gBAC1D,WAAW,EAAE,UAAU;gBACvB,SAAS,EAAE,SAAS;aACrB,CAAC;SACH,CAAC,CAAC;QAEH,MAAM,MAAM,GAAwB,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;QAG1D,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;YACjB,IAAI,MAAM,CAAC,KAAK,KAAK,uBAAuB,EAAE,CAAC;gBAE7C,MAAM,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;gBAC7D,SAAS;YACX,CAAC;iBAAM,IAAI,MAAM,CAAC,KAAK,KAAK,WAAW,EAAE,CAAC;gBAExC,QAAQ,GAAG,QAAQ,GAAG,CAAC,CAAC;gBACxB,MAAM,CAAC,KAAK,CAAC,oCAAoC,QAAQ,UAAU,CAAC,CAAC;gBACrE,SAAS;YACX,CAAC;iBAAM,IAAI,MAAM,CAAC,KAAK,KAAK,eAAe,EAAE,CAAC;gBAE5C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;gBAC5C,MAAM,CAAC,gBAAgB,CACrB,IAAI,KAAK,CAAC,+CAA+C,CAAC,EAC1D;oBACE,IAAI,EAAE;wBACJ,WAAW,EAAE,eAAe;wBAC5B,MAAM,EAAE,sBAAsB;qBAC/B;iBACF,CACF,CAAC;gBACF,MAAM,IAAI,UAAU,CAAC,8BAA8B,CAAC,CAAC;YACvD,CAAC;iBAAM,IAAI,MAAM,CAAC,KAAK,KAAK,eAAe,EAAE,CAAC;gBAE5C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;gBAC5C,MAAM,CAAC,gBAAgB,CAAC,IAAI,KAAK,CAAC,2BAA2B,CAAC,EAAE;oBAC9D,IAAI,EAAE;wBACJ,WAAW,EAAE,eAAe;wBAC5B,MAAM,EAAE,sBAAsB;qBAC/B;iBACF,CAAC,CAAC;gBACH,MAAM,IAAI,UAAU,CAAC,2BAA2B,CAAC,CAAC;YACpD,CAAC;iBAAM,CAAC;gBAEN,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;gBAC5C,MAAM,CAAC,gBAAgB,CACrB,IAAI,KAAK,CAAC,sBAAsB,MAAM,CAAC,KAAK,EAAE,CAAC,EAC/C;oBACE,IAAI,EAAE;wBACJ,WAAW,EAAE,MAAM,CAAC,KAAK;wBACzB,MAAM,EAAE,sBAAsB;qBAC/B;oBACD,KAAK,EAAE;wBACL,iBAAiB,EAAE,MAAM,CAAC,iBAAiB;qBAC5C;iBACF,CACF,CAAC;gBACF,MAAM,IAAI,UAAU,CAClB,MAAM,CAAC,iBAAiB,IAAI,gBAAgB,MAAM,CAAC,KAAK,EAAE,CAC3D,CAAC;YACJ,CAAC;QACH,CAAC;QAGD,IAAI,MAAM,CAAC,YAAY,EAAE,CAAC;YACxB,OAAO,MAAuB,CAAC;QACjC,CAAC;IACH,CAAC;IAGD,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAC;IAC5C,MAAM,CAAC,gBAAgB,CACrB,IAAI,KAAK,CAAC,sDAAsD,CAAC,EACjE;QACE,IAAI,EAAE;YACJ,WAAW,EAAE,SAAS;YACtB,MAAM,EAAE,sBAAsB;SAC/B;KACF,CACF,CAAC;IACF,MAAM,IAAI,UAAU,CAAC,sCAAsC,CAAC,CAAC;AAC/D,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,KAAK;IACzB,IAAI,CAAC;QAEH,MAAM,cAAc,GAAG,MAAM,kBAAkB,EAAE,CAAC;QAIlD,OAAO,CAAC,GAAG,CACT,GAAG,CACD;;EAEN,cAAc,CAAC,yBAAyB;;6DAEmB,EACrD;YACE,WAAW,EAAE,OAAO;SACrB,CACF,CACF,CAAC;QAGF,IAAI,CAAC;YACH,MAAM,GAAG,CAAC,cAAc,CAAC,yBAAyB,CAAC,CAAC;QACtD,CAAC;QAAC,MAAM,CAAC;QAET,CAAC;QAGD,IAAI,aAA4B,CAAC;QACjC,IAAI,CAAC;YACH,aAAa,GAAG,MAAM,YAAY,CAChC,cAAc,CAAC,WAAW,EAC1B,cAAc,CAAC,QAAQ,EACvB,cAAc,CAAC,UAAU,CAC1B,CAAC;QACJ,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,IAAI,GAAG,YAAY,UAAU,EAAE,CAAC;gBAC9B,OAAO,oCAAoC,CACzC,GAAG,GAAG,CAAC,OAAO,uCAAuC,CACtD,CAAC;YACJ,CAAC;iBAAM,CAAC;gBACN,OAAO,oCAAoC,CACzC,6IAA6I,CAC9I,CAAC;YACJ,CAAC;QACH,CAAC;QAGD,MAAM,aAAa,CAAC,aAAa,CAAC,CAAC;IACrC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,KAAK,EAAE,cAAc,CAAC,CAAC;QACpC,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC","sourcesContent":["import opn from \"open\";\nimport { logger } from \"../common/logger.js\";\nimport { OAuthResponse, saveAuthState } from \"./tokens.js\";\nimport box from \"../common/utils/box.js\";\nimport { printCriticalFailureToConsoleAndExit } from \"../common/output.js\";\n\nexport const CLIENT_ID = \"mYLGcH7kB4P0pw0HAk6GH7raRwYhSlW4\";\nexport const AUTH0_DOMAIN = \"auth.zuplo.com\";\nexport const OAUTH_SCOPE = \"offline_access\";\nexport const OAUTH_AUDIENCE = \"https://dev.zuplo.com/\";\n\ninterface DeviceCodeResponse {\n device_code: string;\n user_code: string;\n verification_uri: string;\n verification_uri_complete: string;\n expires_in: number;\n interval: number;\n}\n\ninterface DeviceTokenResponse extends OAuthResponse {\n error?: string;\n error_description?: string;\n}\n\nclass OAuthError extends Error {}\n\n/**\n * Initiates the device authorization flow\n */\nasync function initiateDeviceFlow(): Promise<DeviceCodeResponse> {\n const response = await fetch(`https://${AUTH0_DOMAIN}/oauth/device/code`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: new URLSearchParams({\n client_id: CLIENT_ID,\n scope: OAUTH_SCOPE,\n audience: OAUTH_AUDIENCE,\n }),\n });\n\n if (!response.ok) {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let errorDetails: any = {};\n try {\n errorDetails = await response.json();\n } catch {\n // If response body is not JSON, continue with status text\n }\n\n const Sentry = await import(\"@sentry/node\");\n const errorMessage =\n errorDetails.error_description ||\n errorDetails.error ||\n response.statusText;\n\n Sentry.captureException(\n new Error(`Failed to initiate device flow: ${errorMessage}`),\n {\n tags: {\n oauth_error: errorDetails.error || \"device_code_failed\",\n source: \"cli_device_flow_init\",\n status_code: response.status,\n },\n extra: {\n error_description: errorDetails.error_description,\n error_details: errorDetails,\n status: response.status,\n status_text: response.statusText,\n },\n }\n );\n\n throw new Error(`Failed to initiate device flow: ${errorMessage}`);\n }\n\n return response.json();\n}\n\n/**\n * Polls for the device token\n */\nasync function pollForToken(\n deviceCode: string,\n interval: number,\n expiresIn: number\n): Promise<OAuthResponse> {\n const startTime = Date.now();\n const expirationTime = startTime + expiresIn * 1000;\n\n while (Date.now() < expirationTime) {\n // Wait for the specified interval before polling\n await new Promise((resolve) => setTimeout(resolve, interval * 1000));\n\n const response = await fetch(`https://${AUTH0_DOMAIN}/oauth/token`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: new URLSearchParams({\n grant_type: \"urn:ietf:params:oauth:grant-type:device_code\",\n device_code: deviceCode,\n client_id: CLIENT_ID,\n }),\n });\n\n const result: DeviceTokenResponse = await response.json();\n\n // Check for specific device flow errors\n if (result.error) {\n if (result.error === \"authorization_pending\") {\n // User hasn't authorized yet, continue polling\n logger.debug(\"Authorization pending, continuing to poll...\");\n continue;\n } else if (result.error === \"slow_down\") {\n // Increase polling interval as requested by the server\n interval = interval + 5;\n logger.debug(`Slowing down polling interval to ${interval} seconds`);\n continue;\n } else if (result.error === \"expired_token\") {\n // Device code has expired\n const Sentry = await import(\"@sentry/node\");\n Sentry.captureException(\n new Error(\"Device code expired before user authorization\"),\n {\n tags: {\n oauth_error: \"expired_token\",\n source: \"cli_device_flow_poll\",\n },\n }\n );\n throw new OAuthError(\"The device code has expired.\");\n } else if (result.error === \"access_denied\") {\n // User denied the authorization\n const Sentry = await import(\"@sentry/node\");\n Sentry.captureException(new Error(\"User denied authorization\"), {\n tags: {\n oauth_error: \"access_denied\",\n source: \"cli_device_flow_poll\",\n },\n });\n throw new OAuthError(\"Authorization was denied.\");\n } else {\n // Unknown error\n const Sentry = await import(\"@sentry/node\");\n Sentry.captureException(\n new Error(`Device flow error: ${result.error}`),\n {\n tags: {\n oauth_error: result.error,\n source: \"cli_device_flow_poll\",\n },\n extra: {\n error_description: result.error_description,\n },\n }\n );\n throw new OAuthError(\n result.error_description || `OAuth error: ${result.error}`\n );\n }\n }\n\n // Success! We have the tokens\n if (result.access_token) {\n return result as OAuthResponse;\n }\n }\n\n // Timeout reached\n const Sentry = await import(\"@sentry/node\");\n Sentry.captureException(\n new Error(\"Device flow timed out waiting for user authorization\"),\n {\n tags: {\n oauth_error: \"timeout\",\n source: \"cli_device_flow_poll\",\n },\n }\n );\n throw new OAuthError(\"Timed out waiting for authorization.\");\n}\n\nexport async function login() {\n try {\n // Step 1: Initiate device flow\n const deviceResponse = await initiateDeviceFlow();\n\n // Step 2: Print login message\n // eslint-disable-next-line no-console\n console.log(\n box(\n ` To login, please visit:\n\n${deviceResponse.verification_uri_complete}\n\nAfter completing login in the browser you can close the tab.`,\n {\n borderColor: \"white\",\n }\n )\n );\n\n // Step 3: Try to open the browser automatically\n try {\n await opn(deviceResponse.verification_uri_complete);\n } catch {\n // Ignore\n }\n\n // Step 4: Poll for the token\n let tokenResponse: OAuthResponse;\n try {\n tokenResponse = await pollForToken(\n deviceResponse.device_code,\n deviceResponse.interval,\n deviceResponse.expires_in\n );\n } catch (err) {\n if (err instanceof OAuthError) {\n return printCriticalFailureToConsoleAndExit(\n `${err.message}. Please run the login command again.`\n );\n } else {\n return printCriticalFailureToConsoleAndExit(\n \"An error occurred while attempting to authenticate. Please run the login command again. If the problem persists, contact support@zuplo.com.\"\n );\n }\n }\n\n // Step 5: Save the authentication state\n await saveAuthState(tokenResponse);\n } catch (error) {\n logger.error(error, \"Login failed\");\n throw error;\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/login/tokens.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,aAAa;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAOD,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,CAAC,
|
|
1
|
+
{"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../../src/login/tokens.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,aAAa;IAC5B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAOD,wBAAsB,kBAAkB,CACtC,YAAY,EAAE,MAAM,GACnB,OAAO,CAAC,aAAa,CAAC,CAkDxB;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CA8BhE;AAED,wBAAsB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAWxE"}
|
package/dist/login/tokens.js
CHANGED
|
@@ -20,7 +20,30 @@ export async function refreshAccessToken(refreshToken) {
|
|
|
20
20
|
}),
|
|
21
21
|
});
|
|
22
22
|
if (!response.ok) {
|
|
23
|
-
|
|
23
|
+
let errorDetails = {};
|
|
24
|
+
try {
|
|
25
|
+
errorDetails = await response.json();
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
}
|
|
29
|
+
const Sentry = await import("@sentry/node");
|
|
30
|
+
const errorMessage = errorDetails.error_description ||
|
|
31
|
+
errorDetails.error ||
|
|
32
|
+
response.statusText;
|
|
33
|
+
Sentry.captureException(new Error(`Failed to refresh token: ${errorMessage}`), {
|
|
34
|
+
tags: {
|
|
35
|
+
oauth_error: errorDetails.error || "refresh_token_failed",
|
|
36
|
+
source: "cli_refresh_token",
|
|
37
|
+
status_code: response.status,
|
|
38
|
+
},
|
|
39
|
+
extra: {
|
|
40
|
+
error_description: errorDetails.error_description,
|
|
41
|
+
error_details: errorDetails,
|
|
42
|
+
status: response.status,
|
|
43
|
+
status_text: response.statusText,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
throw new Error(`Failed to refresh token: ${errorMessage}`);
|
|
24
47
|
}
|
|
25
48
|
return response.json();
|
|
26
49
|
}
|
package/dist/login/tokens.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/login/tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAC;AACjC,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAC7C,OAAO,EAAE,yBAAyB,EAAE,MAAM,qBAAqB,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAgBrD,MAAM,CAAC,KAAK,UAAU,kBAAkB,CACtC,YAAoB;IAEpB,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,WAAW,YAAY,cAAc,EAAE;QAClE,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,mCAAmC;SACpD;QACD,IAAI,EAAE,IAAI,eAAe,CAAC;YACxB,UAAU,EAAE,eAAe;YAC3B,SAAS,EAAE,SAAS;YACpB,aAAa,EAAE,YAAY;SAC5B,CAAC;KACH,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"tokens.js","sourceRoot":"","sources":["../../src/login/tokens.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, mkdirSync } from \"node:fs\";\nimport { readFile, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { decodeJwt } from \"jose\";\nimport { ZUPLO_AUTH_FILE_NAME } from \"../common/constants.js\";\nimport { logger } from \"../common/logger.js\";\nimport { printDiagnosticsToConsole } from \"../common/output.js\";\nimport { ZUPLO_XDG_STATE_HOME } from \"../common/xdg/lib.js\";\nimport { AUTH0_DOMAIN, CLIENT_ID } from \"./login.js\";\n\nexport interface OAuthResponse {\n refresh_token?: string;\n access_token: string;\n id_token: string;\n expires_in: number;\n token_type: string;\n scope: string;\n}\n\n/**\n * Refreshes the access token using the provided refresh token.\n * @param refreshToken The refresh token to use for obtaining a new access token.\n * @returns A promise resolving to the new authentication state.\n */\nexport async function refreshAccessToken(\n refreshToken: string\n): Promise<OAuthResponse> {\n const response = await fetch(`https://${AUTH0_DOMAIN}/oauth/token`, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/x-www-form-urlencoded\",\n },\n body: new URLSearchParams({\n grant_type: \"refresh_token\",\n client_id: CLIENT_ID,\n refresh_token: refreshToken,\n }),\n });\n\n if (!response.ok) {\n // Parse the error response if available\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n let errorDetails: any = {};\n try {\n errorDetails = await response.json();\n } catch {\n // If response body is not JSON, continue with status text\n }\n\n const Sentry = await import(\"@sentry/node\");\n const errorMessage =\n errorDetails.error_description ||\n errorDetails.error ||\n response.statusText;\n\n Sentry.captureException(\n new Error(`Failed to refresh token: ${errorMessage}`),\n {\n tags: {\n oauth_error: errorDetails.error || \"refresh_token_failed\",\n source: \"cli_refresh_token\",\n status_code: response.status,\n },\n extra: {\n error_description: errorDetails.error_description,\n error_details: errorDetails,\n status: response.status,\n status_text: response.statusText,\n },\n }\n );\n\n throw new Error(`Failed to refresh token: ${errorMessage}`);\n }\n\n return response.json();\n}\n\nexport async function getAuthToken(): Promise<string | undefined> {\n // The auth file doesn't exist.\n if (!existsSync(join(ZUPLO_XDG_STATE_HOME, ZUPLO_AUTH_FILE_NAME))) {\n return;\n }\n\n const rawAuth = await readFile(\n join(ZUPLO_XDG_STATE_HOME, ZUPLO_AUTH_FILE_NAME),\n \"utf-8\"\n );\n const authJson = JSON.parse(rawAuth);\n const jwt = decodeJwt(authJson.access_token);\n\n // The credentials have expired\n if (!jwt.exp || jwt.exp < Date.now() / 1000) {\n logger.debug(\"Access token expired, attempting to get a new one\");\n // If we have a refresh token try to refresh\n if (authJson.refresh_token) {\n try {\n const newAuth = await refreshAccessToken(authJson.refresh_token);\n await saveAuthState(newAuth);\n return newAuth.access_token;\n } catch (error) {\n logger.error(error, `Failed to refresh access token`);\n return;\n }\n }\n return;\n }\n return authJson.access_token;\n}\n\nexport async function saveAuthState(result: OAuthResponse): Promise<void> {\n try {\n if (!existsSync(ZUPLO_XDG_STATE_HOME)) {\n mkdirSync(ZUPLO_XDG_STATE_HOME, { recursive: true });\n }\n const tokenPath = join(ZUPLO_XDG_STATE_HOME, ZUPLO_AUTH_FILE_NAME);\n await writeFile(tokenPath, JSON.stringify(result));\n } catch (error) {\n logger.error(error, \"Failed to save auth state\");\n printDiagnosticsToConsole(\"Failed to save authorization state.\");\n }\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/cli.ts","../src/types.d.ts","../src/__tests__/archive-utils.test.ts","../src/__tests__/engine.test.ts","../src/__tests__/import-openapi-utils.test.ts","../src/__tests__/import-openapi.test.ts","../src/__tests__/oas-test-data.ts","../src/__tests__/outdated.test.ts","../src/__tests__/populate.test.ts","../src/__tests__/tsconfig-upgrader.test.ts","../src/__tests__/integration/delete.integration.test.ts","../src/__tests__/integration/deploy.integration.test.ts","../src/__tests__/integration/jest-mocks-setup.ts","../src/__tests__/integration/jest-setup.ts","../src/__tests__/integration/link.integration.test.ts","../src/__tests__/integration/list.integration.test.ts","../src/__tests__/integration/test-utils.ts","../src/__tests__/integration/tunnel.integration.test.ts","../src/__tests__/integration/variable.integration.test.ts","../src/build/handler.ts","../src/cmds/build.ts","../src/cmds/compile.ts","../src/cmds/convert.ts","../src/cmds/delete.ts","../src/cmds/deploy.ts","../src/cmds/dev.ts","../src/cmds/editor.ts","../src/cmds/link.ts","../src/cmds/list.ts","../src/cmds/login.ts","../src/cmds/test.ts","../src/cmds/project/create.ts","../src/cmds/project/index.ts","../src/cmds/source/import-openapi.ts","../src/cmds/source/index.ts","../src/cmds/source/migrate.ts","../src/cmds/source/upgrade.ts","../src/cmds/source/migrate/handler.ts","../src/cmds/source/migrate/runner.ts","../src/cmds/source/migrate/stringify-config.test.ts","../src/cmds/source/migrate/stringify-config.ts","../src/cmds/source/migrate/types.ts","../src/cmds/tunnel/create.ts","../src/cmds/tunnel/delete.ts","../src/cmds/tunnel/describe.ts","../src/cmds/tunnel/index.ts","../src/cmds/tunnel/list.ts","../src/cmds/tunnel/rotate-token.ts","../src/cmds/tunnel/services/describe.ts","../src/cmds/tunnel/services/index.ts","../src/cmds/tunnel/services/update.ts","../src/cmds/variable/create.ts","../src/cmds/variable/index.ts","../src/cmds/variable/update.ts","../src/common/alias.ts","../src/common/args.ts","../src/common/constants.ts","../src/common/handler.ts","../src/common/logger.ts","../src/common/models.ts","../src/common/outdated.ts","../src/common/output.ts","../src/common/populate.ts","../src/common/settings.ts","../src/common/worker-output.ts","../src/common/analytics/lib.ts","../src/common/api/lib.ts","../src/common/machine-id/lib.ts","../src/common/middleware/authentication.ts","../src/common/middleware/get-account-param.ts","../src/common/middleware/get-environment-param.ts","../src/common/middleware/get-project-param.ts","../src/common/middleware/logging.ts","../src/common/middleware/user-configuration.ts","../src/common/middleware/user-identification.ts","../src/common/upgraders/lib.ts","../src/common/upgraders/package-json-upgrader.ts","../src/common/upgraders/tsconfig-upgrader.ts","../src/common/upgraders/vscode-settings-json-upgrader.ts","../src/common/utils/box.ts","../src/common/utils/ports.ts","../src/common/utils/pretty-print-environment-prompt.ts","../src/common/utils/types.ts","../src/common/utils/urls.ts","../src/common/validators/file-system-validator.ts","../src/common/validators/lib.ts","../src/common/validators/project-name-validator.ts","../src/common/xdg/lib.ts","../src/compile/handler.ts","../src/convert/engine.ts","../src/convert/handler.ts","../src/convert/routes.legacy.ts","../src/delete/handler.ts","../src/delete/poll-deployment.ts","../src/deploy/archive.ts","../src/deploy/environments.ts","../src/deploy/file-upload.ts","../src/deploy/handler.ts","../src/deploy/poll-deployment.ts","../src/dev/handler.ts","../src/editor/handler.ts","../src/editor/assets/index-7e947de6.js","../src/editor/server/cors-plugin.ts","../src/editor/server/server.ts","../src/editor/server/xfs.ts","../src/link/handler.ts","../src/list/handler.ts","../src/login/
|
|
1
|
+
{"root":["../src/cli.ts","../src/types.d.ts","../src/__tests__/archive-utils.test.ts","../src/__tests__/engine.test.ts","../src/__tests__/import-openapi-utils.test.ts","../src/__tests__/import-openapi.test.ts","../src/__tests__/oas-test-data.ts","../src/__tests__/outdated.test.ts","../src/__tests__/populate.test.ts","../src/__tests__/tsconfig-upgrader.test.ts","../src/__tests__/integration/delete.integration.test.ts","../src/__tests__/integration/deploy.integration.test.ts","../src/__tests__/integration/jest-mocks-setup.ts","../src/__tests__/integration/jest-setup.ts","../src/__tests__/integration/link.integration.test.ts","../src/__tests__/integration/list.integration.test.ts","../src/__tests__/integration/test-utils.ts","../src/__tests__/integration/tunnel.integration.test.ts","../src/__tests__/integration/variable.integration.test.ts","../src/build/handler.ts","../src/cmds/build.ts","../src/cmds/compile.ts","../src/cmds/convert.ts","../src/cmds/delete.ts","../src/cmds/deploy.ts","../src/cmds/dev.ts","../src/cmds/editor.ts","../src/cmds/link.ts","../src/cmds/list.ts","../src/cmds/login.ts","../src/cmds/test.ts","../src/cmds/project/create.ts","../src/cmds/project/index.ts","../src/cmds/source/import-openapi.ts","../src/cmds/source/index.ts","../src/cmds/source/migrate.ts","../src/cmds/source/upgrade.ts","../src/cmds/source/migrate/handler.ts","../src/cmds/source/migrate/runner.ts","../src/cmds/source/migrate/stringify-config.test.ts","../src/cmds/source/migrate/stringify-config.ts","../src/cmds/source/migrate/types.ts","../src/cmds/tunnel/create.ts","../src/cmds/tunnel/delete.ts","../src/cmds/tunnel/describe.ts","../src/cmds/tunnel/index.ts","../src/cmds/tunnel/list.ts","../src/cmds/tunnel/rotate-token.ts","../src/cmds/tunnel/services/describe.ts","../src/cmds/tunnel/services/index.ts","../src/cmds/tunnel/services/update.ts","../src/cmds/variable/create.ts","../src/cmds/variable/index.ts","../src/cmds/variable/update.ts","../src/common/alias.ts","../src/common/args.ts","../src/common/constants.ts","../src/common/handler.ts","../src/common/logger.ts","../src/common/models.ts","../src/common/outdated.ts","../src/common/output.ts","../src/common/populate.ts","../src/common/settings.ts","../src/common/worker-output.ts","../src/common/analytics/lib.ts","../src/common/api/lib.ts","../src/common/machine-id/lib.ts","../src/common/middleware/authentication.ts","../src/common/middleware/get-account-param.ts","../src/common/middleware/get-environment-param.ts","../src/common/middleware/get-project-param.ts","../src/common/middleware/logging.ts","../src/common/middleware/user-configuration.ts","../src/common/middleware/user-identification.ts","../src/common/upgraders/lib.ts","../src/common/upgraders/package-json-upgrader.ts","../src/common/upgraders/tsconfig-upgrader.ts","../src/common/upgraders/vscode-settings-json-upgrader.ts","../src/common/utils/box.ts","../src/common/utils/ports.ts","../src/common/utils/pretty-print-environment-prompt.ts","../src/common/utils/types.ts","../src/common/utils/urls.ts","../src/common/validators/file-system-validator.ts","../src/common/validators/lib.ts","../src/common/validators/project-name-validator.ts","../src/common/xdg/lib.ts","../src/compile/handler.ts","../src/convert/engine.ts","../src/convert/handler.ts","../src/convert/routes.legacy.ts","../src/delete/handler.ts","../src/delete/poll-deployment.ts","../src/deploy/archive.ts","../src/deploy/environments.ts","../src/deploy/file-upload.ts","../src/deploy/handler.ts","../src/deploy/poll-deployment.ts","../src/dev/handler.ts","../src/editor/handler.ts","../src/editor/assets/index-7e947de6.js","../src/editor/server/cors-plugin.ts","../src/editor/server/server.ts","../src/editor/server/xfs.ts","../src/link/handler.ts","../src/list/handler.ts","../src/login/login.ts","../src/login/tokens.ts","../src/project/create/handler.ts","../src/source/import-openapi/handler.ts","../src/source/import-openapi/interfaces.ts","../src/source/import-openapi/utils.ts","../src/source/update/handler.ts","../src/test/esbuild-config.ts","../src/test/handler.ts","../src/test/invoke-test.ts","../src/test/test-files.test.ts","../src/test/test-files.ts","../src/test/esbuild-plugins/node-test-prep-plugin.ts","../src/tunnel/models.ts","../src/tunnel/create/handler.ts","../src/tunnel/delete/handler.ts","../src/tunnel/delete/poll-teardown-operation.ts","../src/tunnel/describe/handler.ts","../src/tunnel/list/handler.ts","../src/tunnel/rotate-token/handler.ts","../src/tunnel/services/describe/handler.ts","../src/tunnel/services/update/handler.ts","../src/tunnel/services/update/poll-provisioning-operations.ts","../src/variable/models.ts","../src/variable/create/handler.ts","../src/variable/update/handler.ts"],"version":"5.8.2"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@zuplo/cli",
|
|
3
|
-
"version": "6.59.
|
|
3
|
+
"version": "6.59.29",
|
|
4
4
|
"repository": "https://github.com/zuplo/zuplo",
|
|
5
5
|
"author": "Zuplo, Inc.",
|
|
6
6
|
"type": "module",
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"@opentelemetry/api": "1.9.0",
|
|
30
30
|
"@sentry/node": "9.22.0",
|
|
31
31
|
"@swc/core": "1.10.18",
|
|
32
|
-
"@zuplo/core": "6.59.
|
|
33
|
-
"@zuplo/openapi-tools": "6.59.
|
|
34
|
-
"@zuplo/runtime": "6.59.
|
|
32
|
+
"@zuplo/core": "6.59.29",
|
|
33
|
+
"@zuplo/openapi-tools": "6.59.29",
|
|
34
|
+
"@zuplo/runtime": "6.59.29",
|
|
35
35
|
"as-table": "1.0.55",
|
|
36
36
|
"chalk": "5.4.1",
|
|
37
37
|
"chokidar": "3.5.3",
|
package/dist/login/html.d.ts
DELETED
|
@@ -1,3 +0,0 @@
|
|
|
1
|
-
export declare const html =
|
|
2
|
-
'<html>\n <head>\n <title id="page-title">Authorization</title>\n <style>\n body {\n font-family:\n -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,\n Arial, sans-serif;\n background-color: #f9fafb;\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100vh;\n margin: 0;\n }\n .container {\n max-width: 400px;\n padding: 2rem;\n background-color: white;\n border-radius: 0.5rem;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n text-align: center;\n border: 1px solid #e5e7eb;\n }\n .icon {\n border-radius: 9999px;\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0 auto 1rem auto;\n }\n .icon.success {\n background-color: #ffe0f7;\n color: #ff00bd;\n }\n .icon.error {\n background-color: #fee2e2;\n color: #dc2626;\n }\n h1 {\n color: #111827;\n font-size: 1.5rem;\n margin-bottom: 0.5rem;\n }\n p {\n color: #6b7280;\n margin-bottom: 1.5rem;\n }\n .error-description {\n background-color: #fef2f2;\n border: 1px solid #fecaca;\n color: #991b1b;\n padding: 1rem;\n border-radius: 0.375rem;\n margin-bottom: 1rem;\n font-size: 0.875rem;\n }\n a {\n color: #d600a0;\n text-decoration: none;\n font-weight: 500;\n }\n a:hover {\n text-decoration: underline;\n }\n button {\n background-color: #ff00bd;\n color: white;\n border: none;\n padding: 0.5rem 1rem;\n border-radius: 0.375rem;\n font-size: 0.875rem;\n cursor: pointer;\n }\n button:hover {\n background-color: #d600a0;\n }\n button.secondary {\n background-color: #6b7280;\n margin-left: 0.5rem;\n }\n button.secondary:hover {\n background-color: #4b5563;\n }\n </style>\n </head>\n <body>\n <div class="container" id="content"></div>\n\n <script>\n // Parse URL parameters\n const urlParams = new URLSearchParams(window.location.search);\n const error = urlParams.get(\'error\');\n const errorDescription = urlParams.get(\'error_description\');\n const errorUri = urlParams.get(\'error_uri\');\n const code = urlParams.get(\'code\');\n\n const pageTitle = document.getElementById(\'page-title\');\n const content = document.getElementById(\'content\');\n\n function createIcon(type) {\n if (type === \'success\') {\n return `\n <div class="icon success">\n <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">\n <path d="M5 13L9 17L19 7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>\n </svg>\n </div>`;\n } else {\n return `\n <div class="icon error">\n <svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">\n <circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/>\n <line x1="15" y1="9" x2="9" y2="15" stroke="currentColor" stroke-width="2"/>\n <line x1="9" y1="9" x2="15" y2="15" stroke="currentColor" stroke-width="2"/>\n </svg>\n </div>`;\n }\n }\n\n function createSupportText() {\n return \'An error occurred during the login process. If the problem continues, please contact our support team at <a href="mailto:support@zuplo.com">support@zuplo.com</a>.\';\n }\n\n if (error) {\n // Handle OAuth error\n pageTitle.textContent = \'Authorization Failed\';\n \n content.innerHTML = `\n ${createIcon(\'error\')}\n <h1>Authorization Failed</h1>\n ${errorDescription ? `<div class="error-description">${errorDescription}</div>` : \'\'}\n <p>${createSupportText()}</p>\n <button onclick="window.close()">Close this tab</button>\n `;\n } else if (code) {\n // Handle successful authorization\n pageTitle.textContent = \'Authorization Successful\';\n content.innerHTML = `\n ${createIcon(\'success\')}\n <h1>Authorization successful</h1>\n <p>Close this tab and return to the Zuplo CLI.</p>\n <button onclick="window.close()">Close this tab</button>\n `;\n } else {\n // Handle unexpected state (no code, no error)\n pageTitle.textContent = \'Authorization Error\';\n \n content.innerHTML = `\n ${createIcon(\'error\')}\n <h1>Authorization Error</h1>\n <div class="error-description">An unexpected error occurred during the login process.</div>\n <p>${createSupportText()}</p>\n <button onclick="window.close()">Close this tab</button>\n `;\n }\n </script>\n </body>\n</html>';
|
|
3
|
-
//# sourceMappingURL=html.d.ts.map
|
package/dist/login/html.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"html.d.ts","sourceRoot":"","sources":["../../src/login/html.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,IAAI,uqKAgKT,CAAC"}
|
package/dist/login/html.js
DELETED
|
@@ -1,162 +0,0 @@
|
|
|
1
|
-
export const html = `<html>
|
|
2
|
-
<head>
|
|
3
|
-
<title id="page-title">Authorization</title>
|
|
4
|
-
<style>
|
|
5
|
-
body {
|
|
6
|
-
font-family:
|
|
7
|
-
-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica,
|
|
8
|
-
Arial, sans-serif;
|
|
9
|
-
background-color: #f9fafb;
|
|
10
|
-
display: flex;
|
|
11
|
-
align-items: center;
|
|
12
|
-
justify-content: center;
|
|
13
|
-
height: 100vh;
|
|
14
|
-
margin: 0;
|
|
15
|
-
}
|
|
16
|
-
.container {
|
|
17
|
-
max-width: 400px;
|
|
18
|
-
padding: 2rem;
|
|
19
|
-
background-color: white;
|
|
20
|
-
border-radius: 0.5rem;
|
|
21
|
-
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
|
|
22
|
-
text-align: center;
|
|
23
|
-
border: 1px solid #e5e7eb;
|
|
24
|
-
}
|
|
25
|
-
.icon {
|
|
26
|
-
border-radius: 9999px;
|
|
27
|
-
width: 48px;
|
|
28
|
-
height: 48px;
|
|
29
|
-
display: flex;
|
|
30
|
-
align-items: center;
|
|
31
|
-
justify-content: center;
|
|
32
|
-
margin: 0 auto 1rem auto;
|
|
33
|
-
}
|
|
34
|
-
.icon.success {
|
|
35
|
-
background-color: #ffe0f7;
|
|
36
|
-
color: #ff00bd;
|
|
37
|
-
}
|
|
38
|
-
.icon.error {
|
|
39
|
-
background-color: #fee2e2;
|
|
40
|
-
color: #dc2626;
|
|
41
|
-
}
|
|
42
|
-
h1 {
|
|
43
|
-
color: #111827;
|
|
44
|
-
font-size: 1.5rem;
|
|
45
|
-
margin-bottom: 0.5rem;
|
|
46
|
-
}
|
|
47
|
-
p {
|
|
48
|
-
color: #6b7280;
|
|
49
|
-
margin-bottom: 1.5rem;
|
|
50
|
-
}
|
|
51
|
-
.error-description {
|
|
52
|
-
background-color: #fef2f2;
|
|
53
|
-
border: 1px solid #fecaca;
|
|
54
|
-
color: #991b1b;
|
|
55
|
-
padding: 1rem;
|
|
56
|
-
border-radius: 0.375rem;
|
|
57
|
-
margin-bottom: 1rem;
|
|
58
|
-
font-size: 0.875rem;
|
|
59
|
-
}
|
|
60
|
-
a {
|
|
61
|
-
color: #d600a0;
|
|
62
|
-
text-decoration: none;
|
|
63
|
-
font-weight: 500;
|
|
64
|
-
}
|
|
65
|
-
a:hover {
|
|
66
|
-
text-decoration: underline;
|
|
67
|
-
}
|
|
68
|
-
button {
|
|
69
|
-
background-color: #ff00bd;
|
|
70
|
-
color: white;
|
|
71
|
-
border: none;
|
|
72
|
-
padding: 0.5rem 1rem;
|
|
73
|
-
border-radius: 0.375rem;
|
|
74
|
-
font-size: 0.875rem;
|
|
75
|
-
cursor: pointer;
|
|
76
|
-
}
|
|
77
|
-
button:hover {
|
|
78
|
-
background-color: #d600a0;
|
|
79
|
-
}
|
|
80
|
-
button.secondary {
|
|
81
|
-
background-color: #6b7280;
|
|
82
|
-
margin-left: 0.5rem;
|
|
83
|
-
}
|
|
84
|
-
button.secondary:hover {
|
|
85
|
-
background-color: #4b5563;
|
|
86
|
-
}
|
|
87
|
-
</style>
|
|
88
|
-
</head>
|
|
89
|
-
<body>
|
|
90
|
-
<div class="container" id="content"></div>
|
|
91
|
-
|
|
92
|
-
<script>
|
|
93
|
-
// Parse URL parameters
|
|
94
|
-
const urlParams = new URLSearchParams(window.location.search);
|
|
95
|
-
const error = urlParams.get('error');
|
|
96
|
-
const errorDescription = urlParams.get('error_description');
|
|
97
|
-
const errorUri = urlParams.get('error_uri');
|
|
98
|
-
const code = urlParams.get('code');
|
|
99
|
-
|
|
100
|
-
const pageTitle = document.getElementById('page-title');
|
|
101
|
-
const content = document.getElementById('content');
|
|
102
|
-
|
|
103
|
-
function createIcon(type) {
|
|
104
|
-
if (type === 'success') {
|
|
105
|
-
return \`
|
|
106
|
-
<div class="icon success">
|
|
107
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
108
|
-
<path d="M5 13L9 17L19 7" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"/>
|
|
109
|
-
</svg>
|
|
110
|
-
</div>\`;
|
|
111
|
-
} else {
|
|
112
|
-
return \`
|
|
113
|
-
<div class="icon error">
|
|
114
|
-
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
115
|
-
<circle cx="12" cy="12" r="10" stroke="currentColor" stroke-width="2"/>
|
|
116
|
-
<line x1="15" y1="9" x2="9" y2="15" stroke="currentColor" stroke-width="2"/>
|
|
117
|
-
<line x1="9" y1="9" x2="15" y2="15" stroke="currentColor" stroke-width="2"/>
|
|
118
|
-
</svg>
|
|
119
|
-
</div>\`;
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
function createSupportText() {
|
|
124
|
-
return 'An error occurred during the login process. If the problem continues, please contact our support team at <a href="mailto:support@zuplo.com">support@zuplo.com</a>.';
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (error) {
|
|
128
|
-
// Handle OAuth error
|
|
129
|
-
pageTitle.textContent = 'Authorization Failed';
|
|
130
|
-
|
|
131
|
-
content.innerHTML = \`
|
|
132
|
-
\${createIcon('error')}
|
|
133
|
-
<h1>Authorization Failed</h1>
|
|
134
|
-
\${errorDescription ? \`<div class="error-description">\${errorDescription}</div>\` : ''}
|
|
135
|
-
<p>\${createSupportText()}</p>
|
|
136
|
-
<button onclick="window.close()">Close this tab</button>
|
|
137
|
-
\`;
|
|
138
|
-
} else if (code) {
|
|
139
|
-
// Handle successful authorization
|
|
140
|
-
pageTitle.textContent = 'Authorization Successful';
|
|
141
|
-
content.innerHTML = \`
|
|
142
|
-
\${createIcon('success')}
|
|
143
|
-
<h1>Authorization successful</h1>
|
|
144
|
-
<p>Close this tab and return to the Zuplo CLI.</p>
|
|
145
|
-
<button onclick="window.close()">Close this tab</button>
|
|
146
|
-
\`;
|
|
147
|
-
} else {
|
|
148
|
-
// Handle unexpected state (no code, no error)
|
|
149
|
-
pageTitle.textContent = 'Authorization Error';
|
|
150
|
-
|
|
151
|
-
content.innerHTML = \`
|
|
152
|
-
\${createIcon('error')}
|
|
153
|
-
<h1>Authorization Error</h1>
|
|
154
|
-
<div class="error-description">An unexpected error occurred during the login process.</div>
|
|
155
|
-
<p>\${createSupportText()}</p>
|
|
156
|
-
<button onclick="window.close()">Close this tab</button>
|
|
157
|
-
\`;
|
|
158
|
-
}
|
|
159
|
-
</script>
|
|
160
|
-
</body>
|
|
161
|
-
</html>`;
|
|
162
|
-
//# sourceMappingURL=html.js.map
|
package/dist/login/html.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"html.js","sourceRoot":"","sources":["../../src/login/html.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;QAgKZ,CAAC","sourcesContent":["export const html = `<html>\n <head>\n <title id=\"page-title\">Authorization</title>\n <style>\n body {\n font-family:\n -apple-system, BlinkMacSystemFont, \"Segoe UI\", Roboto, Helvetica,\n Arial, sans-serif;\n background-color: #f9fafb;\n display: flex;\n align-items: center;\n justify-content: center;\n height: 100vh;\n margin: 0;\n }\n .container {\n max-width: 400px;\n padding: 2rem;\n background-color: white;\n border-radius: 0.5rem;\n box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);\n text-align: center;\n border: 1px solid #e5e7eb;\n }\n .icon {\n border-radius: 9999px;\n width: 48px;\n height: 48px;\n display: flex;\n align-items: center;\n justify-content: center;\n margin: 0 auto 1rem auto;\n }\n .icon.success {\n background-color: #ffe0f7;\n color: #ff00bd;\n }\n .icon.error {\n background-color: #fee2e2;\n color: #dc2626;\n }\n h1 {\n color: #111827;\n font-size: 1.5rem;\n margin-bottom: 0.5rem;\n }\n p {\n color: #6b7280;\n margin-bottom: 1.5rem;\n }\n .error-description {\n background-color: #fef2f2;\n border: 1px solid #fecaca;\n color: #991b1b;\n padding: 1rem;\n border-radius: 0.375rem;\n margin-bottom: 1rem;\n font-size: 0.875rem;\n }\n a {\n color: #d600a0;\n text-decoration: none;\n font-weight: 500;\n }\n a:hover {\n text-decoration: underline;\n }\n button {\n background-color: #ff00bd;\n color: white;\n border: none;\n padding: 0.5rem 1rem;\n border-radius: 0.375rem;\n font-size: 0.875rem;\n cursor: pointer;\n }\n button:hover {\n background-color: #d600a0;\n }\n button.secondary {\n background-color: #6b7280;\n margin-left: 0.5rem;\n }\n button.secondary:hover {\n background-color: #4b5563;\n }\n </style>\n </head>\n <body>\n <div class=\"container\" id=\"content\"></div>\n\n <script>\n // Parse URL parameters\n const urlParams = new URLSearchParams(window.location.search);\n const error = urlParams.get('error');\n const errorDescription = urlParams.get('error_description');\n const errorUri = urlParams.get('error_uri');\n const code = urlParams.get('code');\n\n const pageTitle = document.getElementById('page-title');\n const content = document.getElementById('content');\n\n function createIcon(type) {\n if (type === 'success') {\n return \\`\n <div class=\"icon success\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5 13L9 17L19 7\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"/>\n </svg>\n </div>\\`;\n } else {\n return \\`\n <div class=\"icon error\">\n <svg width=\"24\" height=\"24\" viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"2\"/>\n <line x1=\"15\" y1=\"9\" x2=\"9\" y2=\"15\" stroke=\"currentColor\" stroke-width=\"2\"/>\n <line x1=\"9\" y1=\"9\" x2=\"15\" y2=\"15\" stroke=\"currentColor\" stroke-width=\"2\"/>\n </svg>\n </div>\\`;\n }\n }\n\n function createSupportText() {\n return 'An error occurred during the login process. If the problem continues, please contact our support team at <a href=\"mailto:support@zuplo.com\">support@zuplo.com</a>.';\n }\n\n if (error) {\n // Handle OAuth error\n pageTitle.textContent = 'Authorization Failed';\n \n content.innerHTML = \\`\n \\${createIcon('error')}\n <h1>Authorization Failed</h1>\n \\${errorDescription ? \\`<div class=\"error-description\">\\${errorDescription}</div>\\` : ''}\n <p>\\${createSupportText()}</p>\n <button onclick=\"window.close()\">Close this tab</button>\n \\`;\n } else if (code) {\n // Handle successful authorization\n pageTitle.textContent = 'Authorization Successful';\n content.innerHTML = \\`\n \\${createIcon('success')}\n <h1>Authorization successful</h1>\n <p>Close this tab and return to the Zuplo CLI.</p>\n <button onclick=\"window.close()\">Close this tab</button>\n \\`;\n } else {\n // Handle unexpected state (no code, no error)\n pageTitle.textContent = 'Authorization Error';\n \n content.innerHTML = \\`\n \\${createIcon('error')}\n <h1>Authorization Error</h1>\n <div class=\"error-description\">An unexpected error occurred during the login process.</div>\n <p>\\${createSupportText()}</p>\n <button onclick=\"window.close()\">Close this tab</button>\n \\`;\n }\n </script>\n </body>\n</html>`;\n"]}
|
package/dist/login/server.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/login/server.ts"],"names":[],"mappings":"AAMA,wBAAsB,WAAW,CAAC,gBAAgB,EAAE,MAAM,4BAsCzD"}
|
package/dist/login/server.js
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import http from "node:http";
|
|
2
|
-
import opn from "open";
|
|
3
|
-
import { printCriticalFailureToConsoleAndExit } from "../common/output.js";
|
|
4
|
-
import { html } from "./html.js";
|
|
5
|
-
import { AUTH_SERVER_PORT } from "./login.js";
|
|
6
|
-
export async function browserAuth(authorizationUrl) {
|
|
7
|
-
let params;
|
|
8
|
-
const handler = (req, res) => {
|
|
9
|
-
if (!req.url) {
|
|
10
|
-
throw new Error("Bad url");
|
|
11
|
-
}
|
|
12
|
-
const url = new URL(req.url, `http://localhost:${AUTH_SERVER_PORT}`);
|
|
13
|
-
if (url.pathname === "/") {
|
|
14
|
-
params = url.searchParams;
|
|
15
|
-
res.writeHead(200, { "Content-Type": "text/html" });
|
|
16
|
-
res.end(html);
|
|
17
|
-
}
|
|
18
|
-
else {
|
|
19
|
-
res.end("Unsupported route for login server.");
|
|
20
|
-
}
|
|
21
|
-
};
|
|
22
|
-
const server = http.createServer(handler).listen(AUTH_SERVER_PORT);
|
|
23
|
-
await opn(authorizationUrl);
|
|
24
|
-
let iterations = 0;
|
|
25
|
-
while (params === undefined) {
|
|
26
|
-
if (iterations++ > 600) {
|
|
27
|
-
server.close();
|
|
28
|
-
await printCriticalFailureToConsoleAndExit("Timed out waiting for login in the browser. Run the zuplo login command again.");
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
await new Promise((resolve) => setTimeout(resolve, 500));
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
server.close();
|
|
35
|
-
return params;
|
|
36
|
-
}
|
|
37
|
-
//# sourceMappingURL=server.js.map
|
package/dist/login/server.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../../src/login/server.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,GAAG,MAAM,MAAM,CAAC;AACvB,OAAO,EAAE,oCAAoC,EAAE,MAAM,qBAAqB,CAAC;AAC3E,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,gBAAwB;IACxD,IAAI,MAAmC,CAAC;IAExC,MAAM,OAAO,GAAG,CAAC,GAAyB,EAAE,GAAwB,EAAE,EAAE;QACtE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,SAAS,CAAC,CAAC;QAC7B,CAAC;QACD,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,oBAAoB,gBAAgB,EAAE,CAAC,CAAC;QAErE,IAAI,GAAG,CAAC,QAAQ,KAAK,GAAG,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,CAAC,YAAY,CAAC;YAC1B,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,cAAc,EAAE,WAAW,EAAE,CAAC,CAAC;YACpD,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChB,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;QACjD,CAAC;IACH,CAAC,CAAC;IAGF,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC;IAGnE,MAAM,GAAG,CAAC,gBAAgB,CAAC,CAAC;IAE5B,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,OAAO,MAAM,KAAK,SAAS,EAAE,CAAC;QAC5B,IAAI,UAAU,EAAE,GAAG,GAAG,EAAE,CAAC;YACvB,MAAM,CAAC,KAAK,EAAE,CAAC;YACf,MAAM,oCAAoC,CACxC,gFAAgF,CACjF,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,MAAM,CAAC,KAAK,EAAE,CAAC;IACf,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import http from \"node:http\";\nimport opn from \"open\";\nimport { printCriticalFailureToConsoleAndExit } from \"../common/output.js\";\nimport { html } from \"./html.js\";\nimport { AUTH_SERVER_PORT } from \"./login.js\";\n\nexport async function browserAuth(authorizationUrl: string) {\n let params: URLSearchParams | undefined;\n\n const handler = (req: http.IncomingMessage, res: http.ServerResponse) => {\n if (!req.url) {\n throw new Error(\"Bad url\");\n }\n const url = new URL(req.url, `http://localhost:${AUTH_SERVER_PORT}`);\n // In here when the server gets a request\n if (url.pathname === \"/\") {\n params = url.searchParams;\n res.writeHead(200, { \"Content-Type\": \"text/html\" });\n res.end(html);\n } else {\n res.end(\"Unsupported route for login server.\");\n }\n };\n\n // Very simple webserver, using Nodes standard http module\n const server = http.createServer(handler).listen(AUTH_SERVER_PORT); // static local port\n\n // Open authorization url in preferred browser, works cross-platform\n await opn(authorizationUrl);\n\n let iterations = 0;\n while (params === undefined) {\n if (iterations++ > 600) {\n server.close();\n await printCriticalFailureToConsoleAndExit(\n \"Timed out waiting for login in the browser. Run the zuplo login command again.\"\n );\n } else {\n await new Promise((resolve) => setTimeout(resolve, 500));\n }\n }\n\n server.close();\n return params;\n}\n"]}
|