@shopify/cli-kit 3.68.1 → 3.69.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/dist/cli/api/graphql/admin/generated/public_api_versions.d.ts +14 -0
- package/dist/cli/api/graphql/admin/generated/public_api_versions.js +28 -0
- package/dist/cli/api/graphql/admin/generated/public_api_versions.js.map +1 -0
- package/dist/private/node/api/graphql.d.ts +1 -1
- package/dist/private/node/api/graphql.js +1 -0
- package/dist/private/node/api/graphql.js.map +1 -1
- package/dist/private/node/api/headers.js +2 -2
- package/dist/private/node/api/headers.js.map +1 -1
- package/dist/private/node/api/rest.js +3 -1
- package/dist/private/node/api/rest.js.map +1 -1
- package/dist/private/node/api.d.ts +2 -2
- package/dist/private/node/api.js +8 -6
- package/dist/private/node/api.js.map +1 -1
- package/dist/private/node/constants.d.ts +0 -1
- package/dist/private/node/constants.js +0 -1
- package/dist/private/node/constants.js.map +1 -1
- package/dist/private/node/demo-recorder.js +1 -0
- package/dist/private/node/demo-recorder.js.map +1 -1
- package/dist/private/node/session/device-authorization.js +15 -7
- package/dist/private/node/session/device-authorization.js.map +1 -1
- package/dist/private/node/session/exchange.d.ts +0 -8
- package/dist/private/node/session/exchange.js +2 -19
- package/dist/private/node/session/exchange.js.map +1 -1
- package/dist/private/node/session/validate.js +1 -0
- package/dist/private/node/session/validate.js.map +1 -1
- package/dist/private/node/session.d.ts +5 -5
- package/dist/private/node/session.js +4 -12
- package/dist/private/node/session.js.map +1 -1
- package/dist/private/node/testing/ui.js +0 -3
- package/dist/private/node/testing/ui.js.map +1 -1
- package/dist/private/node/themes/generate-theme-name.js +1 -0
- package/dist/private/node/themes/generate-theme-name.js.map +1 -1
- package/dist/private/node/ui/components/AutocompletePrompt.test.js +0 -3
- package/dist/private/node/ui/components/AutocompletePrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/Banner.js +1 -0
- package/dist/private/node/ui/components/Banner.js.map +1 -1
- package/dist/private/node/ui/components/ConcurrentOutput.test.js +7 -7
- package/dist/private/node/ui/components/ConcurrentOutput.test.js.map +1 -1
- package/dist/private/node/ui/components/FatalError.js +1 -0
- package/dist/private/node/ui/components/FatalError.js.map +1 -1
- package/dist/private/node/ui/components/List.js +1 -1
- package/dist/private/node/ui/components/List.js.map +1 -1
- package/dist/private/node/ui/components/Prompts/InfoTable.js +1 -0
- package/dist/private/node/ui/components/Prompts/InfoTable.js.map +1 -1
- package/dist/private/node/ui/components/SelectInput.js +1 -1
- package/dist/private/node/ui/components/SelectInput.js.map +1 -1
- package/dist/private/node/ui/components/SelectPrompt.test.js +0 -4
- package/dist/private/node/ui/components/SelectPrompt.test.js.map +1 -1
- package/dist/private/node/ui/components/Table/Row.js.map +1 -1
- package/dist/private/node/ui/components/Tasks.js +2 -1
- package/dist/private/node/ui/components/Tasks.js.map +1 -1
- package/dist/private/node/ui/components/TextPrompt.d.ts +1 -1
- package/dist/private/node/ui/components/TextPrompt.js.map +1 -1
- package/dist/private/node/ui/components/TokenizedText.js +1 -0
- package/dist/private/node/ui/components/TokenizedText.js.map +1 -1
- package/dist/private/node/ui/hooks/use-abort-signal.js +1 -1
- package/dist/private/node/ui/hooks/use-abort-signal.js.map +1 -1
- package/dist/private/node/ui.js +3 -1
- package/dist/private/node/ui.js.map +1 -1
- package/dist/public/common/array.js +1 -0
- package/dist/public/common/array.js.map +1 -1
- package/dist/public/common/string.js +3 -0
- package/dist/public/common/string.js.map +1 -1
- package/dist/public/common/version.d.ts +1 -1
- package/dist/public/common/version.js +1 -1
- package/dist/public/common/version.js.map +1 -1
- package/dist/public/node/api/admin.d.ts +14 -1
- package/dist/public/node/api/admin.js +40 -31
- package/dist/public/node/api/admin.js.map +1 -1
- package/dist/public/node/api/app-management.d.ts +5 -3
- package/dist/public/node/api/app-management.js +16 -11
- package/dist/public/node/api/app-management.js.map +1 -1
- package/dist/public/node/api/graphql.js +13 -1
- package/dist/public/node/api/graphql.js.map +1 -1
- package/dist/public/node/api/rest-api-throttler.js +10 -3
- package/dist/public/node/api/rest-api-throttler.js.map +1 -1
- package/dist/public/node/archiver.js +6 -2
- package/dist/public/node/archiver.js.map +1 -1
- package/dist/public/node/base-command.js +1 -1
- package/dist/public/node/base-command.js.map +1 -1
- package/dist/public/node/context/local.d.ts +0 -9
- package/dist/public/node/context/local.js +0 -13
- package/dist/public/node/context/local.js.map +1 -1
- package/dist/public/node/context/spin.js +1 -1
- package/dist/public/node/context/spin.js.map +1 -1
- package/dist/public/node/custom-oclif-loader.js +5 -4
- package/dist/public/node/custom-oclif-loader.js.map +1 -1
- package/dist/public/node/dot-env.js +2 -1
- package/dist/public/node/dot-env.js.map +1 -1
- package/dist/public/node/environments.js +1 -1
- package/dist/public/node/environments.js.map +1 -1
- package/dist/public/node/error-handler.js +3 -3
- package/dist/public/node/error-handler.js.map +1 -1
- package/dist/public/node/error.d.ts +3 -3
- package/dist/public/node/error.js +29 -3
- package/dist/public/node/error.js.map +1 -1
- package/dist/public/node/framework.js +5 -4
- package/dist/public/node/framework.js.map +1 -1
- package/dist/public/node/fs.d.ts +1 -1
- package/dist/public/node/fs.js +1 -1
- package/dist/public/node/fs.js.map +1 -1
- package/dist/public/node/git.js +2 -0
- package/dist/public/node/git.js.map +1 -1
- package/dist/public/node/github.js +2 -0
- package/dist/public/node/github.js.map +1 -1
- package/dist/public/node/hooks/deprecations.js +1 -1
- package/dist/public/node/hooks/deprecations.js.map +1 -1
- package/dist/public/node/hooks/postrun.js +2 -1
- package/dist/public/node/hooks/postrun.js.map +1 -1
- package/dist/public/node/hooks/prerun.js +1 -1
- package/dist/public/node/hooks/prerun.js.map +1 -1
- package/dist/public/node/http.js +2 -1
- package/dist/public/node/http.js.map +1 -1
- package/dist/public/node/json-schema.d.ts +1 -1
- package/dist/public/node/json-schema.js.map +1 -1
- package/dist/public/node/liquid.js +12 -2
- package/dist/public/node/liquid.js.map +1 -1
- package/dist/public/node/metadata.js +1 -0
- package/dist/public/node/metadata.js.map +1 -1
- package/dist/public/node/monorail.d.ts +2 -1
- package/dist/public/node/monorail.js +1 -1
- package/dist/public/node/monorail.js.map +1 -1
- package/dist/public/node/output.js +2 -1
- package/dist/public/node/output.js.map +1 -1
- package/dist/public/node/ruby.js +1 -0
- package/dist/public/node/ruby.js.map +1 -1
- package/dist/public/node/session.d.ts +7 -6
- package/dist/public/node/session.js +2 -1
- package/dist/public/node/session.js.map +1 -1
- package/dist/public/node/system.js +1 -1
- package/dist/public/node/system.js.map +1 -1
- package/dist/public/node/themes/api.js +34 -4
- package/dist/public/node/themes/api.js.map +1 -1
- package/dist/public/node/themes/factories.js +1 -0
- package/dist/public/node/themes/factories.js.map +1 -1
- package/dist/public/node/themes/types.d.ts +2 -3
- package/dist/public/node/themes/types.js.map +1 -1
- package/dist/public/node/themes/urls.d.ts +1 -0
- package/dist/public/node/themes/urls.js +3 -0
- package/dist/public/node/themes/urls.js.map +1 -1
- package/dist/public/node/tree-kill.js +8 -4
- package/dist/public/node/tree-kill.js.map +1 -1
- package/dist/public/node/ui.js +5 -2
- package/dist/public/node/ui.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -5
- package/assets/auth-error.html +0 -23
- package/assets/empty-url.html +0 -23
- package/assets/favicon.svg +0 -26
- package/assets/missing-code.html +0 -23
- package/assets/missing-state.html +0 -23
- package/assets/style.css +0 -58
- package/assets/success.html +0 -20
- package/dist/private/node/session/authorize.d.ts +0 -5
- package/dist/private/node/session/authorize.js +0 -69
- package/dist/private/node/session/authorize.js.map +0 -1
- package/dist/private/node/session/post-auth.d.ts +0 -10
- package/dist/private/node/session/post-auth.js +0 -61
- package/dist/private/node/session/post-auth.js.map +0 -1
- package/dist/private/node/session/redirect-listener.d.ts +0 -34
- package/dist/private/node/session/redirect-listener.js +0 -105
- package/dist/private/node/session/redirect-listener.js.map +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@shopify/cli-kit",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.69.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A set of utilities, interfaces, and models that are common across all the platform features",
|
|
6
6
|
"keywords": [
|
|
@@ -111,7 +111,6 @@
|
|
|
111
111
|
"execa": "7.2.0",
|
|
112
112
|
"fast-glob": "3.3.1",
|
|
113
113
|
"figures": "5.0.0",
|
|
114
|
-
"find-process": "1.4.7",
|
|
115
114
|
"find-up": "6.3.0",
|
|
116
115
|
"form-data": "4.0.0",
|
|
117
116
|
"fs-extra": "11.1.0",
|
|
@@ -122,7 +121,6 @@
|
|
|
122
121
|
"ink": "4.4.1",
|
|
123
122
|
"is-interactive": "2.0.0",
|
|
124
123
|
"jose": "5.8.0",
|
|
125
|
-
"kill-port-process": "3.1.0",
|
|
126
124
|
"latest-version": "7.0.0",
|
|
127
125
|
"liquidjs": "10.9.2",
|
|
128
126
|
"lodash": "4.17.21",
|
|
@@ -179,9 +177,7 @@
|
|
|
179
177
|
"docs:open": "nx docs:open",
|
|
180
178
|
"lint": "nx lint",
|
|
181
179
|
"lint:ruby": "nx lint:ruby",
|
|
182
|
-
"lint:js": "nx lint:js",
|
|
183
180
|
"lint:fix": "nx lint:fix",
|
|
184
|
-
"lint:js:fix": "nx lint:js:fix",
|
|
185
181
|
"lint:ruby:fix": "nx lint:ruby:fix",
|
|
186
182
|
"test": "nx test",
|
|
187
183
|
"test:ruby": "nx test:ruby",
|
package/assets/auth-error.html
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<title>Shopify CLI</title>
|
|
8
|
-
<link rel="stylesheet" href="style.css">
|
|
9
|
-
<link rel="icon" href="favicon.svg" sizes="any" type="image/svg+xml">
|
|
10
|
-
</head>
|
|
11
|
-
|
|
12
|
-
<body class="body-error">
|
|
13
|
-
<div class="app-error">
|
|
14
|
-
<div class="container">
|
|
15
|
-
<h1>Something went wrong!</h1>
|
|
16
|
-
<p>There was an issue while trying to authenticate.</p>
|
|
17
|
-
<br />
|
|
18
|
-
<br />
|
|
19
|
-
<p>Return to your terminal and try running the previous command again.</p>
|
|
20
|
-
</div>
|
|
21
|
-
</div>
|
|
22
|
-
</body>
|
|
23
|
-
</html>
|
package/assets/empty-url.html
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<title>Shopify CLI</title>
|
|
8
|
-
<link rel="stylesheet" href="style.css">
|
|
9
|
-
<link rel="icon" href="favicon.svg" sizes="any" type="image/svg+xml">
|
|
10
|
-
</head>
|
|
11
|
-
|
|
12
|
-
<body class="body-error">
|
|
13
|
-
<div class="app-error">
|
|
14
|
-
<div class="container">
|
|
15
|
-
<h1>Something went wrong!</h1>
|
|
16
|
-
<p>We received the authentication redirect but the URL is empty.</p>
|
|
17
|
-
<br />
|
|
18
|
-
<br />
|
|
19
|
-
<p>Return to your terminal and try running the previous command again.</p>
|
|
20
|
-
</div>
|
|
21
|
-
</div>
|
|
22
|
-
</body>
|
|
23
|
-
</html>
|
package/assets/favicon.svg
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?>
|
|
2
|
-
<!-- Generator: Adobe Illustrator 23.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
3
|
-
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
4
|
-
viewBox="0 0 109.5 124.5" style="enable-background:new 0 0 109.5 124.5;" xml:space="preserve">
|
|
5
|
-
<style type="text/css">
|
|
6
|
-
.st0{fill:#95BF47;}
|
|
7
|
-
.st1{fill:#5E8E3E;}
|
|
8
|
-
.st2{fill:#FFFFFF;}
|
|
9
|
-
</style>
|
|
10
|
-
<g>
|
|
11
|
-
<path class="st0" d="M95.9,23.9c-0.1-0.6-0.6-1-1.1-1c-0.5,0-9.3-0.2-9.3-0.2s-7.4-7.2-8.1-7.9c-0.7-0.7-2.2-0.5-2.7-0.3
|
|
12
|
-
c0,0-1.4,0.4-3.7,1.1c-0.4-1.3-1-2.8-1.8-4.4c-2.6-5-6.5-7.7-11.1-7.7c0,0,0,0,0,0c-0.3,0-0.6,0-1,0.1c-0.1-0.2-0.3-0.3-0.4-0.5
|
|
13
|
-
c-2-2.2-4.6-3.2-7.7-3.1c-6,0.2-12,4.5-16.8,12.2c-3.4,5.4-6,12.2-6.8,17.5c-6.9,2.1-11.7,3.6-11.8,3.7c-3.5,1.1-3.6,1.2-4,4.5
|
|
14
|
-
c-0.3,2.5-9.5,73-9.5,73l76.4,13.2l33.1-8.2C109.5,115.8,96,24.5,95.9,23.9z M67.2,16.8c-1.8,0.5-3.8,1.2-5.9,1.8
|
|
15
|
-
c0-3-0.4-7.3-1.8-10.9C64,8.6,66.2,13.7,67.2,16.8z M57.2,19.9c-4,1.2-8.4,2.6-12.8,3.9c1.2-4.7,3.6-9.4,6.4-12.5
|
|
16
|
-
c1.1-1.1,2.6-2.4,4.3-3.2C56.9,11.6,57.3,16.5,57.2,19.9z M49.1,4c1.4,0,2.6,0.3,3.6,0.9C51.1,5.8,49.5,7,48,8.6
|
|
17
|
-
c-3.8,4.1-6.7,10.5-7.9,16.6c-3.6,1.1-7.2,2.2-10.5,3.2C31.7,18.8,39.8,4.3,49.1,4z"/>
|
|
18
|
-
<g>
|
|
19
|
-
<path class="st1" d="M94.8,22.9c-0.5,0-9.3-0.2-9.3-0.2s-7.4-7.2-8.1-7.9c-0.3-0.3-0.6-0.4-1-0.5l0,109.7l33.1-8.2
|
|
20
|
-
c0,0-13.5-91.3-13.6-92C95.8,23.3,95.3,22.9,94.8,22.9z"/>
|
|
21
|
-
<path class="st2" d="M58,39.9l-3.8,14.4c0,0-4.3-2-9.4-1.6c-7.5,0.5-7.5,5.2-7.5,6.4c0.4,6.4,17.3,7.8,18.3,22.9
|
|
22
|
-
c0.7,11.9-6.3,20-16.4,20.6c-12.2,0.8-18.9-6.4-18.9-6.4l2.6-11c0,0,6.7,5.1,12.1,4.7c3.5-0.2,4.8-3.1,4.7-5.1
|
|
23
|
-
c-0.5-8.4-14.3-7.9-15.2-21.7c-0.7-11.6,6.9-23.4,23.7-24.4C54.7,38.2,58,39.9,58,39.9z"/>
|
|
24
|
-
</g>
|
|
25
|
-
</g>
|
|
26
|
-
</svg>
|
package/assets/missing-code.html
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<title>Shopify CLI</title>
|
|
8
|
-
<link rel="stylesheet" href="style.css">
|
|
9
|
-
<link rel="icon" href="favicon.svg" sizes="any" type="image/svg+xml">
|
|
10
|
-
</head>
|
|
11
|
-
|
|
12
|
-
<body class="body-error">
|
|
13
|
-
<div class="app-error">
|
|
14
|
-
<div class="container">
|
|
15
|
-
<h1>Something went wrong!</h1>
|
|
16
|
-
<p>The authentication can't continue because the redirect doesn't include the code.</p>
|
|
17
|
-
<br />
|
|
18
|
-
<br />
|
|
19
|
-
<p>Return to your terminal and try running the previous command again.</p>
|
|
20
|
-
</div>
|
|
21
|
-
</div>
|
|
22
|
-
</body>
|
|
23
|
-
</html>
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<title>Shopify CLI</title>
|
|
8
|
-
<link rel="stylesheet" href="style.css">
|
|
9
|
-
<link rel="icon" href="favicon.svg" sizes="any" type="image/svg+xml">
|
|
10
|
-
</head>
|
|
11
|
-
|
|
12
|
-
<body class="body-error">
|
|
13
|
-
<div class="app-error">
|
|
14
|
-
<div class="container">
|
|
15
|
-
<h1>Something went wrong!</h1>
|
|
16
|
-
<p>The authentication can't continue because the redirect doesn't include the state.</p>
|
|
17
|
-
<br />
|
|
18
|
-
<br />
|
|
19
|
-
<p>Return to your terminal and try running the previous command again.</p>
|
|
20
|
-
</div>
|
|
21
|
-
</div>
|
|
22
|
-
</body>
|
|
23
|
-
</html>
|
package/assets/style.css
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
html {
|
|
2
|
-
font-family: -apple-system, BlinkMacSystemFont, San Francisco, Segoe UI, Roboto, Helvetica Neue, sans-serif;
|
|
3
|
-
text-size-adjust: 100%;
|
|
4
|
-
text-rendering: optimizeLegibility;
|
|
5
|
-
-webkit-font-smoothing: antialiased;
|
|
6
|
-
-moz-osx-font-smoothing: grayscale;
|
|
7
|
-
}
|
|
8
|
-
|
|
9
|
-
body {
|
|
10
|
-
font-size: 26px;
|
|
11
|
-
line-height: normal;
|
|
12
|
-
margin: 0;
|
|
13
|
-
padding: 0;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
button, input, optgroup, select, textarea {
|
|
17
|
-
font-family: inherit;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
h1 {
|
|
21
|
-
font-weight: 600;
|
|
22
|
-
font-size: 1em;
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
p {
|
|
26
|
-
font-weight: 400;
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
.body-success {
|
|
30
|
-
color: #F6F6F7;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
.body-error {
|
|
34
|
-
color: #202223;
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
.app-success {
|
|
38
|
-
width: 100vw;
|
|
39
|
-
height: 100vh;
|
|
40
|
-
background-color: #054A49;
|
|
41
|
-
display: flex;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
.app-error {
|
|
45
|
-
width: 100vw;
|
|
46
|
-
height: 100vh;
|
|
47
|
-
background-color: #F6F6F7;
|
|
48
|
-
display: flex;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
.container {
|
|
52
|
-
display: flex;
|
|
53
|
-
flex-direction: column;
|
|
54
|
-
justify-content: center;
|
|
55
|
-
width: 100%;
|
|
56
|
-
height: 100%;
|
|
57
|
-
padding-left: 7.5em;
|
|
58
|
-
}
|
package/assets/success.html
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
<!DOCTYPE html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8">
|
|
5
|
-
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
6
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
7
|
-
<title>Shopify CLI</title>
|
|
8
|
-
<link rel="stylesheet" href="style.css">
|
|
9
|
-
<link rel="icon" href="favicon.svg" sizes="any" type="image/svg+xml">
|
|
10
|
-
</head>
|
|
11
|
-
|
|
12
|
-
<body class="body-success">
|
|
13
|
-
<div class="app-success">
|
|
14
|
-
<div class="container">
|
|
15
|
-
<h1>You've successfully logged into the Shopify CLI!</h1>
|
|
16
|
-
<p>You can close this tab and return to your terminal.</p>
|
|
17
|
-
</div>
|
|
18
|
-
</div>
|
|
19
|
-
</body>
|
|
20
|
-
</html>
|
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
import { clientId } from './identity.js';
|
|
2
|
-
import { listenRedirect } from './redirect-listener.js';
|
|
3
|
-
import { base64URLEncode, randomBytes, randomHex, sha256 } from '../../../public/node/crypto.js';
|
|
4
|
-
import { openURL } from '../../../public/node/system.js';
|
|
5
|
-
import { AbortError, CancelExecution } from '../../../public/node/error.js';
|
|
6
|
-
import { identityFqdn } from '../../../public/node/context/fqdn.js';
|
|
7
|
-
import { keypress, renderConfirmationPrompt } from '../../../public/node/ui.js';
|
|
8
|
-
import { outputInfo } from '../../../public/node/output.js';
|
|
9
|
-
import { runWithTimer } from '../../../public/node/metadata.js';
|
|
10
|
-
import { checkPort as isPortAvailable } from 'get-port-please';
|
|
11
|
-
import findProcess from 'find-process';
|
|
12
|
-
export async function authorize(scopes, state = randomHex(30)) {
|
|
13
|
-
const port = 3456;
|
|
14
|
-
const host = '127.0.0.1';
|
|
15
|
-
const redirectUri = `http://${host}:${port}`;
|
|
16
|
-
const fqdn = await identityFqdn();
|
|
17
|
-
const identityClientId = clientId();
|
|
18
|
-
await validateRedirectionPortAvailability(port);
|
|
19
|
-
let url = `http://${fqdn}/oauth/authorize`;
|
|
20
|
-
const { codeVerifier, codeChallenge } = generateRandomChallengePair();
|
|
21
|
-
const params = {
|
|
22
|
-
client_id: identityClientId,
|
|
23
|
-
scope: scopes.join(' '),
|
|
24
|
-
redirect_uri: redirectUri,
|
|
25
|
-
state,
|
|
26
|
-
response_type: 'code',
|
|
27
|
-
code_challenge_method: 'S256',
|
|
28
|
-
code_challenge: codeChallenge,
|
|
29
|
-
};
|
|
30
|
-
outputInfo('\nTo run this command, log in to Shopify.');
|
|
31
|
-
outputInfo('👉 Press any key to open the login page on your browser');
|
|
32
|
-
await keypress();
|
|
33
|
-
url = `${url}?${new URLSearchParams(params).toString()}`;
|
|
34
|
-
await openURL(url);
|
|
35
|
-
return runWithTimer('cmd_all_timing_prompts_ms')(async () => {
|
|
36
|
-
const result = await listenRedirect(host, port, url);
|
|
37
|
-
if (result.state !== state) {
|
|
38
|
-
throw new AbortError("The state received from the authentication doesn't match the one that initiated the authentication process.");
|
|
39
|
-
}
|
|
40
|
-
return { code: result.code, codeVerifier };
|
|
41
|
-
});
|
|
42
|
-
}
|
|
43
|
-
function generateRandomChallengePair() {
|
|
44
|
-
const codeVerifier = base64URLEncode(randomBytes(32));
|
|
45
|
-
const codeChallenge = base64URLEncode(sha256(codeVerifier));
|
|
46
|
-
return { codeVerifier, codeChallenge };
|
|
47
|
-
}
|
|
48
|
-
async function validateRedirectionPortAvailability(port) {
|
|
49
|
-
const { killPortProcess } = await import('kill-port-process');
|
|
50
|
-
if (await isPortAvailable(port)) {
|
|
51
|
-
return;
|
|
52
|
-
}
|
|
53
|
-
if (await terminateBlockingPortProcessPrompt(port, 'Authentication')) {
|
|
54
|
-
await killPortProcess(port);
|
|
55
|
-
}
|
|
56
|
-
else {
|
|
57
|
-
throw new CancelExecution();
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
async function terminateBlockingPortProcessPrompt(port, stepDescription) {
|
|
61
|
-
const processInfo = await findProcess('port', port);
|
|
62
|
-
const formattedProcessName = processInfo && processInfo.length > 0 && processInfo[0]?.name ? ` (${processInfo[0].name})` : '';
|
|
63
|
-
return renderConfirmationPrompt({
|
|
64
|
-
message: `${stepDescription} requires a port ${port} that's unavailable because it's running another process${formattedProcessName}. Terminate that process?`,
|
|
65
|
-
confirmationMessage: 'Yes, terminate process in order to log in now',
|
|
66
|
-
cancellationMessage: `No, cancel command and try later`,
|
|
67
|
-
});
|
|
68
|
-
}
|
|
69
|
-
//# sourceMappingURL=authorize.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"authorize.js","sourceRoot":"","sources":["../../../../src/private/node/session/authorize.ts"],"names":[],"mappings":"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","sourcesContent":["import {clientId} from './identity.js'\nimport {listenRedirect} from './redirect-listener.js'\nimport {base64URLEncode, randomBytes, randomHex, sha256} from '../../../public/node/crypto.js'\nimport {openURL} from '../../../public/node/system.js'\nimport {AbortError, CancelExecution} from '../../../public/node/error.js'\nimport {identityFqdn} from '../../../public/node/context/fqdn.js'\nimport {keypress, renderConfirmationPrompt} from '../../../public/node/ui.js'\nimport {outputInfo} from '../../../public/node/output.js'\nimport {runWithTimer} from '../../../public/node/metadata.js'\nimport {checkPort as isPortAvailable} from 'get-port-please'\nimport findProcess from 'find-process'\n\nexport interface CodeAuthResult {\n code: string\n codeVerifier: string\n}\n\nexport async function authorize(scopes: string[], state: string = randomHex(30)): Promise<CodeAuthResult> {\n const port = 3456\n const host = '127.0.0.1'\n const redirectUri = `http://${host}:${port}`\n const fqdn = await identityFqdn()\n const identityClientId = clientId()\n\n await validateRedirectionPortAvailability(port)\n\n let url = `http://${fqdn}/oauth/authorize`\n\n const {codeVerifier, codeChallenge} = generateRandomChallengePair()\n\n const params = {\n client_id: identityClientId,\n scope: scopes.join(' '),\n redirect_uri: redirectUri,\n state,\n response_type: 'code',\n code_challenge_method: 'S256',\n code_challenge: codeChallenge,\n }\n\n outputInfo('\\nTo run this command, log in to Shopify.')\n outputInfo('👉 Press any key to open the login page on your browser')\n await keypress()\n\n url = `${url}?${new URLSearchParams(params).toString()}`\n await openURL(url)\n\n return runWithTimer('cmd_all_timing_prompts_ms')(async () => {\n const result = await listenRedirect(host, port, url)\n\n if (result.state !== state) {\n throw new AbortError(\n \"The state received from the authentication doesn't match the one that initiated the authentication process.\",\n )\n }\n\n return {code: result.code, codeVerifier}\n })\n}\n\nfunction generateRandomChallengePair() {\n const codeVerifier = base64URLEncode(randomBytes(32))\n const codeChallenge = base64URLEncode(sha256(codeVerifier))\n return {codeVerifier, codeChallenge}\n}\n\nasync function validateRedirectionPortAvailability(port: number) {\n const {killPortProcess} = await import('kill-port-process')\n\n if (await isPortAvailable(port)) {\n return\n }\n\n if (await terminateBlockingPortProcessPrompt(port, 'Authentication')) {\n await killPortProcess(port)\n } else {\n throw new CancelExecution()\n }\n}\n\nasync function terminateBlockingPortProcessPrompt(port: number, stepDescription: string): Promise<boolean> {\n const processInfo = await findProcess('port', port)\n const formattedProcessName =\n processInfo && processInfo.length > 0 && processInfo[0]?.name ? ` (${processInfo[0].name})` : ''\n\n return renderConfirmationPrompt({\n message: `${stepDescription} requires a port ${port} that's unavailable because it's running another process${formattedProcessName}. Terminate that process?`,\n confirmationMessage: 'Yes, terminate process in order to log in now',\n cancellationMessage: `No, cancel command and try later`,\n })\n}\n"]}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
export declare const getEmptyUrlHTML: () => Promise<string>;
|
|
2
|
-
export declare const getAuthErrorHTML: () => Promise<string>;
|
|
3
|
-
export declare const getMissingCodeHTML: () => Promise<string>;
|
|
4
|
-
export declare const getMissingStateHTML: () => Promise<string>;
|
|
5
|
-
export declare const getSuccessHTML: () => Promise<string>;
|
|
6
|
-
export declare const getStylesheet: () => Promise<string>;
|
|
7
|
-
export declare const getFavicon: () => Promise<string>;
|
|
8
|
-
export declare const EmptyUrlString = "We received the authentication redirect but the URL is empty.";
|
|
9
|
-
export declare const MissingCodeString = "The authentication can't continue because the redirect doesn't include the code.";
|
|
10
|
-
export declare const MissingStateString = "The authentication can't continue because the redirect doesn't include the state.";
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { moduleDirectory } from '../../../public/node/path.js';
|
|
2
|
-
import { readFile, findPathUp } from '../../../public/node/fs.js';
|
|
3
|
-
import { BugError } from '../../../public/node/error.js';
|
|
4
|
-
const HTMLFileNames = [
|
|
5
|
-
'empty-url.html',
|
|
6
|
-
'auth-error.html',
|
|
7
|
-
'missing-code.html',
|
|
8
|
-
'missing-state.html',
|
|
9
|
-
'success.html',
|
|
10
|
-
];
|
|
11
|
-
const StylesheetFilename = 'style.css';
|
|
12
|
-
const FaviconFileName = 'favicon.svg';
|
|
13
|
-
/**
|
|
14
|
-
* Finds the full path of the given file-name from the assets folder.
|
|
15
|
-
*
|
|
16
|
-
* @param fileName - The name of the file to look for.
|
|
17
|
-
* @returns The full path of the file, or null if not found.
|
|
18
|
-
*/
|
|
19
|
-
const getFilePath = async (fileName) => {
|
|
20
|
-
const filePath = await findPathUp(`assets/${fileName}`, {
|
|
21
|
-
type: 'file',
|
|
22
|
-
cwd: moduleDirectory(import.meta.url),
|
|
23
|
-
});
|
|
24
|
-
if (!filePath) {
|
|
25
|
-
throw RedirectPageAssetNotFoundError();
|
|
26
|
-
}
|
|
27
|
-
return filePath;
|
|
28
|
-
};
|
|
29
|
-
export const getEmptyUrlHTML = async () => {
|
|
30
|
-
const filePath = await getFilePath(HTMLFileNames[0]);
|
|
31
|
-
return readFile(filePath);
|
|
32
|
-
};
|
|
33
|
-
export const getAuthErrorHTML = async () => {
|
|
34
|
-
const filePath = await getFilePath(HTMLFileNames[1]);
|
|
35
|
-
return readFile(filePath);
|
|
36
|
-
};
|
|
37
|
-
export const getMissingCodeHTML = async () => {
|
|
38
|
-
const filePath = await getFilePath(HTMLFileNames[2]);
|
|
39
|
-
return readFile(filePath);
|
|
40
|
-
};
|
|
41
|
-
export const getMissingStateHTML = async () => {
|
|
42
|
-
const filePath = await getFilePath(HTMLFileNames[3]);
|
|
43
|
-
return readFile(filePath);
|
|
44
|
-
};
|
|
45
|
-
export const getSuccessHTML = async () => {
|
|
46
|
-
const filePath = await getFilePath(HTMLFileNames[4]);
|
|
47
|
-
return readFile(filePath);
|
|
48
|
-
};
|
|
49
|
-
export const getStylesheet = async () => {
|
|
50
|
-
const filePath = await getFilePath(StylesheetFilename);
|
|
51
|
-
return readFile(filePath);
|
|
52
|
-
};
|
|
53
|
-
export const getFavicon = async () => {
|
|
54
|
-
const filePath = await getFilePath(FaviconFileName);
|
|
55
|
-
return readFile(filePath);
|
|
56
|
-
};
|
|
57
|
-
export const EmptyUrlString = 'We received the authentication redirect but the URL is empty.';
|
|
58
|
-
export const MissingCodeString = "The authentication can't continue because the redirect doesn't include the code.";
|
|
59
|
-
export const MissingStateString = "The authentication can't continue because the redirect doesn't include the state.";
|
|
60
|
-
const RedirectPageAssetNotFoundError = () => new BugError(`Redirect page asset not found`);
|
|
61
|
-
//# sourceMappingURL=post-auth.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"post-auth.js","sourceRoot":"","sources":["../../../../src/private/node/session/post-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,eAAe,EAAC,MAAM,8BAA8B,CAAA;AAC5D,OAAO,EAAC,QAAQ,EAAE,UAAU,EAAC,MAAM,4BAA4B,CAAA;AAC/D,OAAO,EAAC,QAAQ,EAAC,MAAM,+BAA+B,CAAA;AAEtD,MAAM,aAAa,GAAG;IACpB,gBAAgB;IAChB,iBAAiB;IACjB,mBAAmB;IACnB,oBAAoB;IACpB,cAAc;CACN,CAAA;AACV,MAAM,kBAAkB,GAAG,WAAW,CAAA;AACtC,MAAM,eAAe,GAAG,aAAa,CAAA;AAErC;;;;;GAKG;AACH,MAAM,WAAW,GAAG,KAAK,EAAE,QAAgB,EAAmB,EAAE;IAC9D,MAAM,QAAQ,GAAG,MAAM,UAAU,CAAC,UAAU,QAAQ,EAAE,EAAE;QACtD,IAAI,EAAE,MAAM;QACZ,GAAG,EAAE,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;KACtC,CAAC,CAAA;IACF,IAAI,CAAC,QAAQ,EAAE;QACb,MAAM,8BAA8B,EAAE,CAAA;KACvC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,IAAqB,EAAE;IACzD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACpD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,IAAqB,EAAE;IAC1D,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACpD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,IAAqB,EAAE;IAC5D,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACpD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,IAAqB,EAAE;IAC7D,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACpD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,IAAqB,EAAE;IACxD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAA;IACpD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,IAAqB,EAAE;IACvD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,kBAAkB,CAAC,CAAA;IACtD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,IAAqB,EAAE;IACpD,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,eAAe,CAAC,CAAA;IACnD,OAAO,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC3B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,+DAA+D,CAAA;AAE7F,MAAM,CAAC,MAAM,iBAAiB,GAAG,kFAAkF,CAAA;AAEnH,MAAM,CAAC,MAAM,kBAAkB,GAAG,mFAAmF,CAAA;AAErH,MAAM,8BAA8B,GAAG,GAAG,EAAE,CAAC,IAAI,QAAQ,CAAC,+BAA+B,CAAC,CAAA","sourcesContent":["import {moduleDirectory} from '../../../public/node/path.js'\nimport {readFile, findPathUp} from '../../../public/node/fs.js'\nimport {BugError} from '../../../public/node/error.js'\n\nconst HTMLFileNames = [\n 'empty-url.html',\n 'auth-error.html',\n 'missing-code.html',\n 'missing-state.html',\n 'success.html',\n] as const\nconst StylesheetFilename = 'style.css'\nconst FaviconFileName = 'favicon.svg'\n\n/**\n * Finds the full path of the given file-name from the assets folder.\n *\n * @param fileName - The name of the file to look for.\n * @returns The full path of the file, or null if not found.\n */\nconst getFilePath = async (fileName: string): Promise<string> => {\n const filePath = await findPathUp(`assets/${fileName}`, {\n type: 'file',\n cwd: moduleDirectory(import.meta.url),\n })\n if (!filePath) {\n throw RedirectPageAssetNotFoundError()\n }\n return filePath\n}\n\nexport const getEmptyUrlHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[0])\n return readFile(filePath)\n}\n\nexport const getAuthErrorHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[1])\n return readFile(filePath)\n}\n\nexport const getMissingCodeHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[2])\n return readFile(filePath)\n}\n\nexport const getMissingStateHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[3])\n return readFile(filePath)\n}\n\nexport const getSuccessHTML = async (): Promise<string> => {\n const filePath = await getFilePath(HTMLFileNames[4])\n return readFile(filePath)\n}\n\nexport const getStylesheet = async (): Promise<string> => {\n const filePath = await getFilePath(StylesheetFilename)\n return readFile(filePath)\n}\n\nexport const getFavicon = async (): Promise<string> => {\n const filePath = await getFilePath(FaviconFileName)\n return readFile(filePath)\n}\n\nexport const EmptyUrlString = 'We received the authentication redirect but the URL is empty.'\n\nexport const MissingCodeString = \"The authentication can't continue because the redirect doesn't include the code.\"\n\nexport const MissingStateString = \"The authentication can't continue because the redirect doesn't include the state.\"\n\nconst RedirectPageAssetNotFoundError = () => new BugError(`Redirect page asset not found`)\n"]}
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* It represents the result of a redirect.
|
|
3
|
-
*/
|
|
4
|
-
type RedirectCallback = (error: Error | undefined, state: string | undefined, code: string | undefined) => void;
|
|
5
|
-
/**
|
|
6
|
-
* Defines the interface of the options that
|
|
7
|
-
* are used to instantiate a redirect listener.
|
|
8
|
-
*/
|
|
9
|
-
interface RedirectListenerOptions {
|
|
10
|
-
host: string;
|
|
11
|
-
port: number;
|
|
12
|
-
callback: RedirectCallback;
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* When the authentication completes, Identity redirects
|
|
16
|
-
* the user to a URL. In the case of the CLI, the redirect
|
|
17
|
-
* is to localhost passing some parameters that are necessary
|
|
18
|
-
* to continue the authentication. Because of that, we need
|
|
19
|
-
* an HTTP server that runs and listens to the request.
|
|
20
|
-
*/
|
|
21
|
-
export declare class RedirectListener {
|
|
22
|
-
private static createServer;
|
|
23
|
-
port: number;
|
|
24
|
-
host: string;
|
|
25
|
-
server: ReturnType<typeof RedirectListener.createServer>;
|
|
26
|
-
constructor(options: RedirectListenerOptions);
|
|
27
|
-
start(): void;
|
|
28
|
-
stop(): Promise<void>;
|
|
29
|
-
}
|
|
30
|
-
export declare function listenRedirect(host: string, port: number, url: string): Promise<{
|
|
31
|
-
code: string;
|
|
32
|
-
state: string;
|
|
33
|
-
}>;
|
|
34
|
-
export {};
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import { getFavicon, getStylesheet, getEmptyUrlHTML, getAuthErrorHTML, getMissingCodeHTML, getMissingStateHTML, getSuccessHTML, EmptyUrlString, MissingCodeString, MissingStateString, } from './post-auth.js';
|
|
2
|
-
import { AbortError, BugError } from '../../../public/node/error.js';
|
|
3
|
-
import { outputContent, outputInfo, outputToken } from '../../../public/node/output.js';
|
|
4
|
-
import url from 'url';
|
|
5
|
-
import { createServer } from 'http';
|
|
6
|
-
const ResponseTimeoutSeconds = 10;
|
|
7
|
-
const ServerStopDelaySeconds = 0.5;
|
|
8
|
-
/**
|
|
9
|
-
* When the authentication completes, Identity redirects
|
|
10
|
-
* the user to a URL. In the case of the CLI, the redirect
|
|
11
|
-
* is to localhost passing some parameters that are necessary
|
|
12
|
-
* to continue the authentication. Because of that, we need
|
|
13
|
-
* an HTTP server that runs and listens to the request.
|
|
14
|
-
*/
|
|
15
|
-
export class RedirectListener {
|
|
16
|
-
static createServer(callback) {
|
|
17
|
-
const app = async (request, response) => {
|
|
18
|
-
const requestUrl = request.url;
|
|
19
|
-
if (requestUrl?.includes('favicon')) {
|
|
20
|
-
const faviconFile = await getFavicon();
|
|
21
|
-
response.setHeader('Content-Type', 'image/svg+xml');
|
|
22
|
-
response.write(faviconFile);
|
|
23
|
-
response.end();
|
|
24
|
-
return {};
|
|
25
|
-
}
|
|
26
|
-
else if (requestUrl === '/style.css') {
|
|
27
|
-
const stylesheetFile = await getStylesheet();
|
|
28
|
-
response.setHeader('Content-Type', 'text/css');
|
|
29
|
-
response.write(stylesheetFile);
|
|
30
|
-
response.end();
|
|
31
|
-
return {};
|
|
32
|
-
}
|
|
33
|
-
const respond = async (contents, error, state, code) => {
|
|
34
|
-
response.setHeader('Content-Type', 'text/html');
|
|
35
|
-
response.write(contents);
|
|
36
|
-
response.end();
|
|
37
|
-
callback(error, state, code);
|
|
38
|
-
return {};
|
|
39
|
-
};
|
|
40
|
-
// If there was an empty/malformed URL sent back.
|
|
41
|
-
if (!requestUrl) {
|
|
42
|
-
const file = await getEmptyUrlHTML();
|
|
43
|
-
const err = new BugError(EmptyUrlString);
|
|
44
|
-
return respond(file, err, undefined, undefined);
|
|
45
|
-
}
|
|
46
|
-
// If an error was returned by the Identity server.
|
|
47
|
-
const queryObject = url.parse(requestUrl, true).query;
|
|
48
|
-
if (queryObject.error && queryObject.error_description) {
|
|
49
|
-
const file = await getAuthErrorHTML();
|
|
50
|
-
const err = new AbortError(`${queryObject.error_description}`);
|
|
51
|
-
return respond(file, err, undefined, undefined);
|
|
52
|
-
}
|
|
53
|
-
// If the code isn't present in the URL.
|
|
54
|
-
if (!queryObject.code) {
|
|
55
|
-
const file = await getMissingCodeHTML();
|
|
56
|
-
const err = new BugError(MissingCodeString);
|
|
57
|
-
return respond(file, err, undefined, undefined);
|
|
58
|
-
}
|
|
59
|
-
// If the state isn't present in the URL.
|
|
60
|
-
if (!queryObject.state) {
|
|
61
|
-
const file = await getMissingStateHTML();
|
|
62
|
-
const err = new BugError(MissingStateString);
|
|
63
|
-
return respond(file, err, undefined, undefined);
|
|
64
|
-
}
|
|
65
|
-
const file = await getSuccessHTML();
|
|
66
|
-
return respond(file, undefined, `${queryObject.code}`, `${queryObject.state}`);
|
|
67
|
-
};
|
|
68
|
-
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
69
|
-
return createServer(app);
|
|
70
|
-
}
|
|
71
|
-
constructor(options) {
|
|
72
|
-
this.port = options.port;
|
|
73
|
-
this.host = options.host;
|
|
74
|
-
this.server = RedirectListener.createServer(options.callback);
|
|
75
|
-
}
|
|
76
|
-
start() {
|
|
77
|
-
this.server.listen({ port: this.port, host: this.host }, () => { });
|
|
78
|
-
}
|
|
79
|
-
async stop() {
|
|
80
|
-
await this.server.close();
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
export async function listenRedirect(host, port, url) {
|
|
84
|
-
const result = await new Promise((resolve, reject) => {
|
|
85
|
-
const timeout = setTimeout(() => {
|
|
86
|
-
const message = '\nAuto-open timed out. Open the login page: ';
|
|
87
|
-
outputInfo(outputContent `${message}${outputToken.link('Log in to Shopify Partners', url)}\n`);
|
|
88
|
-
}, ResponseTimeoutSeconds * 1000);
|
|
89
|
-
const callback = (error, code, state) => {
|
|
90
|
-
clearTimeout(timeout);
|
|
91
|
-
setTimeout(() => {
|
|
92
|
-
// eslint-disable-next-line @typescript-eslint/no-floating-promises
|
|
93
|
-
redirectListener.stop();
|
|
94
|
-
if (error)
|
|
95
|
-
reject(error);
|
|
96
|
-
else
|
|
97
|
-
resolve({ code: code, state: state });
|
|
98
|
-
}, ServerStopDelaySeconds * 1000);
|
|
99
|
-
};
|
|
100
|
-
const redirectListener = new RedirectListener({ host, port, callback });
|
|
101
|
-
redirectListener.start();
|
|
102
|
-
});
|
|
103
|
-
return result;
|
|
104
|
-
}
|
|
105
|
-
//# sourceMappingURL=redirect-listener.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"redirect-listener.js","sourceRoot":"","sources":["../../../../src/private/node/session/redirect-listener.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getFavicon,\n getStylesheet,\n getEmptyUrlHTML,\n getAuthErrorHTML,\n getMissingCodeHTML,\n getMissingStateHTML,\n getSuccessHTML,\n EmptyUrlString,\n MissingCodeString,\n MissingStateString,\n} from './post-auth.js'\nimport {AbortError, BugError} from '../../../public/node/error.js'\nimport {outputContent, outputInfo, outputToken} from '../../../public/node/output.js'\nimport url from 'url'\nimport {createServer, Server, IncomingMessage, ServerResponse} from 'http'\n\nconst ResponseTimeoutSeconds = 10\nconst ServerStopDelaySeconds = 0.5\n\n/**\n * It represents the result of a redirect.\n */\ntype RedirectCallback = (error: Error | undefined, state: string | undefined, code: string | undefined) => void\n\n/**\n * Defines the interface of the options that\n * are used to instantiate a redirect listener.\n */\ninterface RedirectListenerOptions {\n host: string\n port: number\n callback: RedirectCallback\n}\n/**\n * When the authentication completes, Identity redirects\n * the user to a URL. In the case of the CLI, the redirect\n * is to localhost passing some parameters that are necessary\n * to continue the authentication. Because of that, we need\n * an HTTP server that runs and listens to the request.\n */\nexport class RedirectListener {\n private static createServer(callback: RedirectCallback): Server {\n const app = async (request: IncomingMessage, response: ServerResponse) => {\n const requestUrl = request.url\n if (requestUrl?.includes('favicon')) {\n const faviconFile = await getFavicon()\n response.setHeader('Content-Type', 'image/svg+xml')\n response.write(faviconFile)\n response.end()\n return {}\n } else if (requestUrl === '/style.css') {\n const stylesheetFile = await getStylesheet()\n response.setHeader('Content-Type', 'text/css')\n response.write(stylesheetFile)\n response.end()\n return {}\n }\n\n const respond = async (contents: string, error?: Error, state?: string, code?: string) => {\n response.setHeader('Content-Type', 'text/html')\n response.write(contents)\n response.end()\n callback(error, state, code)\n return {}\n }\n\n // If there was an empty/malformed URL sent back.\n if (!requestUrl) {\n const file = await getEmptyUrlHTML()\n const err = new BugError(EmptyUrlString)\n return respond(file, err, undefined, undefined)\n }\n\n // If an error was returned by the Identity server.\n const queryObject = url.parse(requestUrl, true).query\n if (queryObject.error && queryObject.error_description) {\n const file = await getAuthErrorHTML()\n const err = new AbortError(`${queryObject.error_description}`)\n return respond(file, err, undefined, undefined)\n }\n\n // If the code isn't present in the URL.\n if (!queryObject.code) {\n const file = await getMissingCodeHTML()\n const err = new BugError(MissingCodeString)\n return respond(file, err, undefined, undefined)\n }\n\n // If the state isn't present in the URL.\n if (!queryObject.state) {\n const file = await getMissingStateHTML()\n const err = new BugError(MissingStateString)\n return respond(file, err, undefined, undefined)\n }\n\n const file = await getSuccessHTML()\n return respond(file, undefined, `${queryObject.code}`, `${queryObject.state}`)\n }\n\n // eslint-disable-next-line @typescript-eslint/no-misused-promises\n return createServer(app)\n }\n\n port: number\n host: string\n server: ReturnType<typeof RedirectListener.createServer>\n\n constructor(options: RedirectListenerOptions) {\n this.port = options.port\n this.host = options.host\n this.server = RedirectListener.createServer(options.callback)\n }\n\n start(): void {\n this.server.listen({port: this.port, host: this.host}, () => {})\n }\n\n async stop(): Promise<void> {\n await this.server.close()\n }\n}\n\nexport async function listenRedirect(host: string, port: number, url: string): Promise<{code: string; state: string}> {\n const result = await new Promise<{code: string; state: string}>((resolve, reject) => {\n const timeout = setTimeout(() => {\n const message = '\\nAuto-open timed out. Open the login page: '\n outputInfo(outputContent`${message}${outputToken.link('Log in to Shopify Partners', url)}\\n`)\n }, ResponseTimeoutSeconds * 1000)\n\n const callback: RedirectCallback = (error, code, state) => {\n clearTimeout(timeout)\n setTimeout(() => {\n // eslint-disable-next-line @typescript-eslint/no-floating-promises\n redirectListener.stop()\n if (error) reject(error)\n else resolve({code: code as string, state: state as string})\n }, ServerStopDelaySeconds * 1000)\n }\n\n const redirectListener = new RedirectListener({host, port, callback})\n redirectListener.start()\n })\n return result\n}\n"]}
|