shopify 3.93.0 → 3.93.2
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/assets/hydrogen/starter/CHANGELOG.md +64 -0
- package/dist/assets/hydrogen/starter/app/components/Aside.tsx +4 -2
- package/dist/assets/hydrogen/starter/app/components/CartMain.tsx +6 -3
- package/dist/assets/hydrogen/starter/app/components/CartSummary.tsx +117 -23
- package/dist/assets/hydrogen/starter/app/components/Header.tsx +3 -3
- package/dist/assets/hydrogen/starter/app/components/PaginatedResourceSection.tsx +24 -4
- package/dist/assets/hydrogen/starter/app/components/ProductPrice.tsx +1 -1
- package/dist/assets/hydrogen/starter/app/routes/[robots.txt].tsx +14 -53
- package/dist/assets/hydrogen/starter/app/routes/_index.tsx +11 -4
- package/dist/assets/hydrogen/starter/app/routes/account.$.tsx +1 -1
- package/dist/assets/hydrogen/starter/app/routes/account.addresses.tsx +2 -2
- package/dist/assets/hydrogen/starter/app/routes/account.profile.tsx +1 -1
- package/dist/assets/hydrogen/starter/package.json +5 -5
- package/dist/assets/hydrogen/starter/storefrontapi.generated.d.ts +0 -11
- package/dist/assets/hydrogen/starter/vite.config.ts +1 -1
- package/dist/assets/hydrogen/vite/vite.config.js +1 -1
- package/dist/{chunk-DLK7L2KZ.js → chunk-4QL77VYJ.js} +3 -3
- package/dist/{chunk-U7JC7ESX.js → chunk-4VZV4LQX.js} +2 -2
- package/dist/{chunk-MYTB32VB.js → chunk-5FCKEHCK.js} +177 -181
- package/dist/{chunk-POO2TAEO.js → chunk-DDTYWTF2.js} +1 -1
- package/dist/{chunk-XV44IQDO.js → chunk-FYQIRCLV.js} +1 -1
- package/dist/{chunk-O6CC6JKI.js → chunk-IG47ZDRU.js} +1 -1
- package/dist/{chunk-SBSUITP6.js → chunk-MX6WWR5F.js} +1 -1
- package/dist/{chunk-P3ASN7B5.js → chunk-XVFYDYZA.js} +1 -1
- package/dist/cli/commands/store/auth.d.ts +1 -0
- package/dist/cli/commands/store/auth.js +10 -3
- package/dist/cli/commands/store/execute.d.ts +1 -0
- package/dist/cli/commands/store/execute.js +7 -4
- package/dist/cli/services/store/auth/callback.d.ts +8 -0
- package/dist/cli/services/store/auth/callback.js +140 -0
- package/dist/cli/services/store/{auth-config.js → auth/config.js} +1 -1
- package/dist/cli/services/store/auth/existing-scopes.d.ts +5 -0
- package/dist/cli/services/store/auth/existing-scopes.js +40 -0
- package/dist/cli/services/store/auth/index.d.ts +18 -0
- package/dist/cli/services/store/auth/index.js +88 -0
- package/dist/cli/services/store/auth/pkce.d.ts +36 -0
- package/dist/cli/services/store/auth/pkce.js +49 -0
- package/dist/cli/services/store/{auth-recovery.js → auth/recovery.js} +1 -1
- package/dist/cli/services/store/auth/result.d.ts +24 -0
- package/dist/cli/services/store/auth/result.js +39 -0
- package/dist/cli/services/store/auth/scopes.d.ts +4 -0
- package/dist/cli/services/store/auth/scopes.js +53 -0
- package/dist/cli/services/store/auth/session-lifecycle.d.ts +3 -0
- package/dist/cli/services/store/auth/session-lifecycle.js +69 -0
- package/dist/cli/services/store/{session.d.ts → auth/session-store.d.ts} +1 -2
- package/dist/cli/services/store/auth/session-store.js +127 -0
- package/dist/cli/services/store/auth/token-client.d.ts +40 -0
- package/dist/cli/services/store/auth/token-client.js +95 -0
- package/dist/cli/services/store/{admin-graphql-context.d.ts → execute/admin-context.d.ts} +3 -2
- package/dist/cli/services/store/execute/admin-context.js +41 -0
- package/dist/cli/services/store/execute/admin-transport.d.ts +6 -0
- package/dist/cli/services/store/{admin-graphql-transport.js → execute/admin-transport.js} +7 -7
- package/dist/cli/services/store/{execute.d.ts → execute/index.d.ts} +2 -3
- package/dist/cli/services/store/{execute.js → execute/index.js} +4 -11
- package/dist/cli/services/store/{execute-request.d.ts → execute/request.d.ts} +0 -2
- package/dist/cli/services/store/{execute-request.js → execute/request.js} +1 -2
- package/dist/cli/services/store/execute/result.d.ts +3 -0
- package/dist/cli/services/store/execute/result.js +29 -0
- package/dist/cli/services/store/{graphql-targets.d.ts → execute/targets.d.ts} +2 -3
- package/dist/cli/services/store/{graphql-targets.js → execute/targets.js} +5 -11
- package/dist/{error-handler-IRR4EZPS.js → error-handler-GZ2I7BG5.js} +1 -1
- package/dist/hooks/postrun.js +1 -1
- package/dist/hooks/prerun.js +1 -1
- package/dist/{http-proxy-node16-KBILO6A6.js → http-proxy-node16-DSQMBVDI.js} +1 -1
- package/dist/index.js +873 -865
- package/dist/{lib-EN3PX6IK.js → lib-GGVLMXY5.js} +1 -1
- package/dist/{local-PQUMWHWR.js → local-WHQ3ZS4K.js} +1 -1
- package/dist/{node-package-manager-HIOT5VLV.js → node-package-manager-6XMPTNUI.js} +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/{ui-QBSPD4RX.js → ui-GZ7DOSHP.js} +1 -1
- package/dist/{workerd-QSZBPNES.js → workerd-LJU6AVMQ.js} +1 -1
- package/oclif.manifest.json +24 -5
- package/package.json +7 -7
- package/dist/assets/hydrogen/starter/app/routes/api.$version.[graphql.json].tsx +0 -14
- package/dist/cli/services/store/admin-graphql-context.js +0 -103
- package/dist/cli/services/store/admin-graphql-transport.d.ts +0 -9
- package/dist/cli/services/store/auth.d.ts +0 -61
- package/dist/cli/services/store/auth.js +0 -326
- package/dist/cli/services/store/execute-result.d.ts +0 -1
- package/dist/cli/services/store/execute-result.js +0 -18
- package/dist/cli/services/store/session.js +0 -69
- /package/dist/cli/services/store/{auth-config.d.ts → auth/config.d.ts} +0 -0
- /package/dist/cli/services/store/{auth-recovery.d.ts → auth/recovery.d.ts} +0 -0
- /package/dist/{morph-6DCXNO2H.js → morph-Q32V442A.js} +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Ac as l,Bc as m,Cc as n,Dc as o,Ec as p,Fc as q,Gc as r,ec as a,fc as b,rc as c,sc as d,tc as e,uc as f,vc as g,wc as h,xc as i,yc as j,zc as k}from"./chunk-
|
|
1
|
+
import{Ac as l,Bc as m,Cc as n,Dc as o,Ec as p,Fc as q,Gc as r,ec as a,fc as b,rc as c,sc as d,tc as e,uc as f,vc as g,wc as h,xc as i,yc as j,zc as k}from"./chunk-4QL77VYJ.js";import"./chunk-XVFYDYZA.js";import"./chunk-FYQIRCLV.js";import"./chunk-QJEBL3WX.js";import"./chunk-EENHXSWU.js";import"./chunk-NOSKVZWJ.js";import"./chunk-T4M5CWAO.js";import"./chunk-PRVQAHWI.js";import"./chunk-QUTQDXSL.js";import"./chunk-VPRTJUIN.js";export{b as handleCtrlC,r as isTTY,q as keypress,a as render,k as renderAutocompletePrompt,c as renderConcurrent,j as renderConfirmationPrompt,p as renderDangerousConfirmationPrompt,g as renderError,h as renderFatalError,d as renderInfo,i as renderSelectPrompt,n as renderSingleTask,e as renderSuccess,l as renderTable,m as renderTasks,o as renderTextPrompt,f as renderWarning};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{$a as x,Va as b,Wa as k,Xa as E,Y as v,Ya as A,Za as I,_a as L,nb as s,pb as B,qb as O}from"./chunk-5FCKEHCK.js";import"./chunk-KADPE3PY.js";import"./chunk-IG47ZDRU.js";import"./chunk-4VZV4LQX.js";import"./chunk-PRKBO42R.js";import"./chunk-MX6WWR5F.js";import{Gd as q,Jc as R,Qa as g,ic as N,tc as w,va as y}from"./chunk-4QL77VYJ.js";import"./chunk-XVFYDYZA.js";import"./chunk-FYQIRCLV.js";import"./chunk-QJEBL3WX.js";import"./chunk-EENHXSWU.js";import{d as h,g as f}from"./chunk-NOSKVZWJ.js";import"./chunk-T4M5CWAO.js";import"./chunk-PRVQAHWI.js";import"./chunk-QUTQDXSL.js";import{g as p}from"./chunk-VPRTJUIN.js";p();import{createRequire as C}from"node:module";async function ee({root:c,appPort:D,inspectorPort:P,assetsPort:S,debug:U=!1,watch:W=!1,buildPathWorkerFile:$,buildPathClient:M,env:l}){let{createMiniOxygen:F,Response:u}=await v("@shopify/mini-oxygen",c).catch(L);k({Response:u});async function _(){let r=C(import.meta.url).resolve("@shopify/hydrogen/customer-account.schema.json");return new u(g(r),{headers:{"Content-Type":"application/json"}})}let t="hydrogen",o=h(c,$),m=()=>y(o).catch(e=>{throw new R(`Could not read worker file.
|
|
2
2
|
|
|
3
3
|
`+e.stack,"Did you build the project?")}),i=F({debug:U,port:D,host:"localhost",liveReload:W,requestHook:x,inspectorPort:P,inspectWorkerName:t,assets:{port:S,directory:M},workers:[{name:"hydrogen:middleware",modules:!0,script:`export default { fetch: (request, env) => {
|
|
4
4
|
const url = new URL(request.url);
|
package/oclif.manifest.json
CHANGED
|
@@ -4426,7 +4426,7 @@
|
|
|
4426
4426
|
],
|
|
4427
4427
|
"args": {
|
|
4428
4428
|
"routeName": {
|
|
4429
|
-
"description": "The route to generate. One of home,page,cart,products,collections,policies,blogs,account,search,robots,sitemap,
|
|
4429
|
+
"description": "The route to generate. One of home,page,cart,products,collections,policies,blogs,account,search,robots,sitemap,all.",
|
|
4430
4430
|
"name": "routeName",
|
|
4431
4431
|
"options": [
|
|
4432
4432
|
"home",
|
|
@@ -4440,7 +4440,6 @@
|
|
|
4440
4440
|
"search",
|
|
4441
4441
|
"robots",
|
|
4442
4442
|
"sitemap",
|
|
4443
|
-
"tokenlessApi",
|
|
4444
4443
|
"all"
|
|
4445
4444
|
],
|
|
4446
4445
|
"required": true
|
|
@@ -5743,9 +5742,19 @@
|
|
|
5743
5742
|
"descriptionWithMarkdown": "Authenticates the app against the specified store for store commands and stores an online access token for later reuse.\n\nRe-run this command if the stored token is missing, expires, or no longer has the scopes you need.",
|
|
5744
5743
|
"enableJsonFlag": false,
|
|
5745
5744
|
"examples": [
|
|
5746
|
-
"<%= config.bin %> <%= command.id %> --store shop.myshopify.com --scopes read_products,write_products"
|
|
5745
|
+
"<%= config.bin %> <%= command.id %> --store shop.myshopify.com --scopes read_products,write_products",
|
|
5746
|
+
"<%= config.bin %> <%= command.id %> --store shop.myshopify.com --scopes read_products,write_products --json"
|
|
5747
5747
|
],
|
|
5748
5748
|
"flags": {
|
|
5749
|
+
"json": {
|
|
5750
|
+
"allowNo": false,
|
|
5751
|
+
"char": "j",
|
|
5752
|
+
"description": "Output the result as JSON. Automatically disables color output.",
|
|
5753
|
+
"env": "SHOPIFY_FLAG_JSON",
|
|
5754
|
+
"hidden": false,
|
|
5755
|
+
"name": "json",
|
|
5756
|
+
"type": "boolean"
|
|
5757
|
+
},
|
|
5749
5758
|
"no-color": {
|
|
5750
5759
|
"allowNo": false,
|
|
5751
5760
|
"description": "Disable color output.",
|
|
@@ -5803,7 +5812,8 @@
|
|
|
5803
5812
|
"examples": [
|
|
5804
5813
|
"<%= config.bin %> <%= command.id %> --store shop.myshopify.com --query \"query { shop { name } }\"",
|
|
5805
5814
|
"<%= config.bin %> <%= command.id %> --store shop.myshopify.com --query-file ./operation.graphql --variables '{\"id\":\"gid://shopify/Product/1\"}'",
|
|
5806
|
-
"<%= config.bin %> <%= command.id %> --store shop.myshopify.com --query \"mutation { shop { id } }\" --allow-mutations"
|
|
5815
|
+
"<%= config.bin %> <%= command.id %> --store shop.myshopify.com --query \"mutation { shop { id } }\" --allow-mutations",
|
|
5816
|
+
"<%= config.bin %> <%= command.id %> --store shop.myshopify.com --query \"query { shop { name } }\" --json"
|
|
5807
5817
|
],
|
|
5808
5818
|
"flags": {
|
|
5809
5819
|
"allow-mutations": {
|
|
@@ -5813,6 +5823,15 @@
|
|
|
5813
5823
|
"name": "allow-mutations",
|
|
5814
5824
|
"type": "boolean"
|
|
5815
5825
|
},
|
|
5826
|
+
"json": {
|
|
5827
|
+
"allowNo": false,
|
|
5828
|
+
"char": "j",
|
|
5829
|
+
"description": "Output the result as JSON. Automatically disables color output.",
|
|
5830
|
+
"env": "SHOPIFY_FLAG_JSON",
|
|
5831
|
+
"hidden": false,
|
|
5832
|
+
"name": "json",
|
|
5833
|
+
"type": "boolean"
|
|
5834
|
+
},
|
|
5816
5835
|
"no-color": {
|
|
5817
5836
|
"allowNo": false,
|
|
5818
5837
|
"description": "Disable color output.",
|
|
@@ -8380,5 +8399,5 @@
|
|
|
8380
8399
|
"summary": "Trigger delivery of a sample webhook topic payload to a designated address."
|
|
8381
8400
|
}
|
|
8382
8401
|
},
|
|
8383
|
-
"version": "3.93.
|
|
8402
|
+
"version": "3.93.2"
|
|
8384
8403
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "shopify",
|
|
3
|
-
"version": "3.93.
|
|
3
|
+
"version": "3.93.2",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A CLI tool to build for the Shopify platform",
|
|
6
6
|
"keywords": [
|
|
@@ -49,12 +49,12 @@
|
|
|
49
49
|
"@oclif/core": "4.5.3",
|
|
50
50
|
"@oclif/plugin-commands": "4.1.33",
|
|
51
51
|
"@oclif/plugin-plugins": "5.4.47",
|
|
52
|
-
"@shopify/app": "3.93.
|
|
53
|
-
"@shopify/cli-kit": "3.93.
|
|
54
|
-
"@shopify/plugin-cloudflare": "3.93.
|
|
55
|
-
"@shopify/plugin-did-you-mean": "3.93.
|
|
56
|
-
"@shopify/theme": "3.93.
|
|
57
|
-
"@shopify/cli-hydrogen": "11.1.
|
|
52
|
+
"@shopify/app": "3.93.2",
|
|
53
|
+
"@shopify/cli-kit": "3.93.2",
|
|
54
|
+
"@shopify/plugin-cloudflare": "3.93.2",
|
|
55
|
+
"@shopify/plugin-did-you-mean": "3.93.2",
|
|
56
|
+
"@shopify/theme": "3.93.2",
|
|
57
|
+
"@shopify/cli-hydrogen": "11.1.14",
|
|
58
58
|
"@types/global-agent": "3.0.0",
|
|
59
59
|
"@vitest/coverage-istanbul": "^3.1.4",
|
|
60
60
|
"esbuild-plugin-copy": "^2.1.1"
|
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
import type {Route} from './+types/api.$version.[graphql.json]';
|
|
2
|
-
|
|
3
|
-
export async function action({params, context, request}: Route.ActionArgs) {
|
|
4
|
-
const response = await fetch(
|
|
5
|
-
`https://${context.env.PUBLIC_CHECKOUT_DOMAIN}/api/${params.version}/graphql.json`,
|
|
6
|
-
{
|
|
7
|
-
method: 'POST',
|
|
8
|
-
body: request.body,
|
|
9
|
-
headers: request.headers,
|
|
10
|
-
},
|
|
11
|
-
);
|
|
12
|
-
|
|
13
|
-
return new Response(response.body, {headers: new Headers(response.headers)});
|
|
14
|
-
}
|
|
@@ -1,103 +0,0 @@
|
|
|
1
|
-
import { fetchApiVersions } from '@shopify/cli-kit/node/api/admin';
|
|
2
|
-
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
3
|
-
import { fetch } from '@shopify/cli-kit/node/http';
|
|
4
|
-
import { outputContent, outputDebug, outputToken } from '@shopify/cli-kit/node/output';
|
|
5
|
-
import { maskToken, STORE_AUTH_APP_CLIENT_ID } from './auth-config.js';
|
|
6
|
-
import { createStoredStoreAuthError, reauthenticateStoreAuthError } from './auth-recovery.js';
|
|
7
|
-
import { clearStoredStoreAppSession, getStoredStoreAppSession, isSessionExpired, setStoredStoreAppSession, } from './session.js';
|
|
8
|
-
async function refreshStoreToken(session) {
|
|
9
|
-
if (!session.refreshToken) {
|
|
10
|
-
throw reauthenticateStoreAuthError(`No refresh token stored for ${session.store}.`, session.store, session.scopes.join(','));
|
|
11
|
-
}
|
|
12
|
-
const endpoint = `https://${session.store}/admin/oauth/access_token`;
|
|
13
|
-
outputDebug(outputContent `Refreshing expired token for ${outputToken.raw(session.store)} (expired at ${outputToken.raw(session.expiresAt ?? 'unknown')}, refresh_token=${outputToken.raw(maskToken(session.refreshToken))})`);
|
|
14
|
-
const response = await fetch(endpoint, {
|
|
15
|
-
method: 'POST',
|
|
16
|
-
headers: { 'Content-Type': 'application/json' },
|
|
17
|
-
body: JSON.stringify({
|
|
18
|
-
client_id: STORE_AUTH_APP_CLIENT_ID,
|
|
19
|
-
grant_type: 'refresh_token',
|
|
20
|
-
refresh_token: session.refreshToken,
|
|
21
|
-
}),
|
|
22
|
-
});
|
|
23
|
-
const body = await response.text();
|
|
24
|
-
if (!response.ok) {
|
|
25
|
-
outputDebug(outputContent `Token refresh failed with HTTP ${outputToken.raw(String(response.status))}: ${outputToken.raw(body.slice(0, 300))}`);
|
|
26
|
-
clearStoredStoreAppSession(session.store, session.userId);
|
|
27
|
-
throw reauthenticateStoreAuthError(`Token refresh failed for ${session.store} (HTTP ${response.status}).`, session.store, session.scopes.join(','));
|
|
28
|
-
}
|
|
29
|
-
let data;
|
|
30
|
-
try {
|
|
31
|
-
data = JSON.parse(body);
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
clearStoredStoreAppSession(session.store, session.userId);
|
|
35
|
-
throw new AbortError('Received an invalid refresh response from Shopify.');
|
|
36
|
-
}
|
|
37
|
-
if (!data.access_token) {
|
|
38
|
-
clearStoredStoreAppSession(session.store, session.userId);
|
|
39
|
-
throw reauthenticateStoreAuthError(`Token refresh returned an invalid response for ${session.store}.`, session.store, session.scopes.join(','));
|
|
40
|
-
}
|
|
41
|
-
const now = Date.now();
|
|
42
|
-
const expiresAt = data.expires_in ? new Date(now + data.expires_in * 1000).toISOString() : session.expiresAt;
|
|
43
|
-
const refreshedSession = {
|
|
44
|
-
...session,
|
|
45
|
-
accessToken: data.access_token,
|
|
46
|
-
refreshToken: data.refresh_token ?? session.refreshToken,
|
|
47
|
-
expiresAt,
|
|
48
|
-
refreshTokenExpiresAt: data.refresh_token_expires_in
|
|
49
|
-
? new Date(now + data.refresh_token_expires_in * 1000).toISOString()
|
|
50
|
-
: session.refreshTokenExpiresAt,
|
|
51
|
-
acquiredAt: new Date(now).toISOString(),
|
|
52
|
-
};
|
|
53
|
-
outputDebug(outputContent `Token refresh succeeded for ${outputToken.raw(session.store)}: ${outputToken.raw(maskToken(session.accessToken))} → ${outputToken.raw(maskToken(refreshedSession.accessToken))}, new expiry ${outputToken.raw(expiresAt ?? 'unknown')}`);
|
|
54
|
-
setStoredStoreAppSession(refreshedSession);
|
|
55
|
-
return refreshedSession;
|
|
56
|
-
}
|
|
57
|
-
async function loadStoredStoreSession(store) {
|
|
58
|
-
let session = getStoredStoreAppSession(store);
|
|
59
|
-
if (!session) {
|
|
60
|
-
throw createStoredStoreAuthError(store);
|
|
61
|
-
}
|
|
62
|
-
outputDebug(outputContent `Loaded stored session for ${outputToken.raw(store)}: token=${outputToken.raw(maskToken(session.accessToken))}, expires=${outputToken.raw(session.expiresAt ?? 'unknown')}`);
|
|
63
|
-
if (isSessionExpired(session)) {
|
|
64
|
-
session = await refreshStoreToken(session);
|
|
65
|
-
}
|
|
66
|
-
return session;
|
|
67
|
-
}
|
|
68
|
-
async function resolveApiVersion(options) {
|
|
69
|
-
const { session, adminSession, userSpecifiedVersion } = options;
|
|
70
|
-
if (userSpecifiedVersion === 'unstable')
|
|
71
|
-
return userSpecifiedVersion;
|
|
72
|
-
let availableVersions;
|
|
73
|
-
try {
|
|
74
|
-
availableVersions = await fetchApiVersions(adminSession);
|
|
75
|
-
}
|
|
76
|
-
catch (error) {
|
|
77
|
-
if (error instanceof AbortError &&
|
|
78
|
-
error.message.includes(`Error connecting to your store ${adminSession.storeFqdn}:`) &&
|
|
79
|
-
/\b(?:401|404)\b/.test(error.message)) {
|
|
80
|
-
clearStoredStoreAppSession(session.store, session.userId);
|
|
81
|
-
throw reauthenticateStoreAuthError(`Stored app authentication for ${session.store} is no longer valid.`, session.store, session.scopes.join(','));
|
|
82
|
-
}
|
|
83
|
-
throw error;
|
|
84
|
-
}
|
|
85
|
-
if (!userSpecifiedVersion) {
|
|
86
|
-
const supportedVersions = availableVersions.filter((version) => version.supported).map((version) => version.handle);
|
|
87
|
-
return supportedVersions.sort().reverse()[0];
|
|
88
|
-
}
|
|
89
|
-
const versionList = availableVersions.map((version) => version.handle);
|
|
90
|
-
if (versionList.includes(userSpecifiedVersion))
|
|
91
|
-
return userSpecifiedVersion;
|
|
92
|
-
throw new AbortError(`Invalid API version: ${userSpecifiedVersion}`, `Allowed versions: ${versionList.join(', ')}`);
|
|
93
|
-
}
|
|
94
|
-
export async function prepareAdminStoreGraphQLContext(input) {
|
|
95
|
-
const session = await loadStoredStoreSession(input.store);
|
|
96
|
-
const adminSession = {
|
|
97
|
-
token: session.accessToken,
|
|
98
|
-
storeFqdn: session.store,
|
|
99
|
-
};
|
|
100
|
-
const version = await resolveApiVersion({ session, adminSession, userSpecifiedVersion: input.userSpecifiedVersion });
|
|
101
|
-
return { adminSession, version, sessionUserId: session.userId };
|
|
102
|
-
}
|
|
103
|
-
//# sourceMappingURL=admin-graphql-context.js.map
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { AdminSession } from '@shopify/cli-kit/node/session';
|
|
2
|
-
import { PreparedStoreExecuteRequest } from './execute-request.js';
|
|
3
|
-
export declare function runAdminStoreGraphQLOperation(input: {
|
|
4
|
-
store: string;
|
|
5
|
-
adminSession: AdminSession;
|
|
6
|
-
sessionUserId: string;
|
|
7
|
-
version: string;
|
|
8
|
-
request: PreparedStoreExecuteRequest;
|
|
9
|
-
}): Promise<unknown>;
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { openURL } from '@shopify/cli-kit/node/system';
|
|
2
|
-
interface StoreAuthInput {
|
|
3
|
-
store: string;
|
|
4
|
-
scopes: string;
|
|
5
|
-
}
|
|
6
|
-
interface StoreTokenResponse {
|
|
7
|
-
access_token: string;
|
|
8
|
-
token_type?: string;
|
|
9
|
-
scope?: string;
|
|
10
|
-
expires_in?: number;
|
|
11
|
-
refresh_token?: string;
|
|
12
|
-
refresh_token_expires_in?: number;
|
|
13
|
-
associated_user_scope?: string;
|
|
14
|
-
associated_user?: {
|
|
15
|
-
id: number;
|
|
16
|
-
first_name?: string;
|
|
17
|
-
last_name?: string;
|
|
18
|
-
email?: string;
|
|
19
|
-
account_owner?: boolean;
|
|
20
|
-
locale?: string;
|
|
21
|
-
collaborator?: boolean;
|
|
22
|
-
email_verified?: boolean;
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
interface WaitForAuthCodeOptions {
|
|
26
|
-
store: string;
|
|
27
|
-
state: string;
|
|
28
|
-
port: number;
|
|
29
|
-
timeoutMs?: number;
|
|
30
|
-
onListening?: () => void | Promise<void>;
|
|
31
|
-
}
|
|
32
|
-
export declare function generateCodeVerifier(): string;
|
|
33
|
-
export declare function computeCodeChallenge(verifier: string): string;
|
|
34
|
-
export declare function parseStoreAuthScopes(input: string): string[];
|
|
35
|
-
export declare function buildStoreAuthUrl(options: {
|
|
36
|
-
store: string;
|
|
37
|
-
scopes: string[];
|
|
38
|
-
state: string;
|
|
39
|
-
redirectUri: string;
|
|
40
|
-
codeChallenge: string;
|
|
41
|
-
}): string;
|
|
42
|
-
export declare function waitForStoreAuthCode({ store, state, port, timeoutMs, onListening, }: WaitForAuthCodeOptions): Promise<string>;
|
|
43
|
-
export declare function exchangeStoreAuthCodeForToken(options: {
|
|
44
|
-
store: string;
|
|
45
|
-
code: string;
|
|
46
|
-
codeVerifier: string;
|
|
47
|
-
redirectUri: string;
|
|
48
|
-
}): Promise<StoreTokenResponse>;
|
|
49
|
-
interface StoreAuthPresenter {
|
|
50
|
-
openingBrowser: () => void;
|
|
51
|
-
manualAuthUrl: (authorizationUrl: string) => void;
|
|
52
|
-
success: (store: string, email?: string) => void;
|
|
53
|
-
}
|
|
54
|
-
interface StoreAuthDependencies {
|
|
55
|
-
openURL: typeof openURL;
|
|
56
|
-
waitForStoreAuthCode: typeof waitForStoreAuthCode;
|
|
57
|
-
exchangeStoreAuthCodeForToken: typeof exchangeStoreAuthCodeForToken;
|
|
58
|
-
presenter: StoreAuthPresenter;
|
|
59
|
-
}
|
|
60
|
-
export declare function authenticateStoreWithApp(input: StoreAuthInput, dependencies?: StoreAuthDependencies): Promise<void>;
|
|
61
|
-
export {};
|
|
@@ -1,326 +0,0 @@
|
|
|
1
|
-
import { DEFAULT_STORE_AUTH_PORT, STORE_AUTH_APP_CLIENT_ID, STORE_AUTH_CALLBACK_PATH, maskToken, storeAuthRedirectUri } from './auth-config.js';
|
|
2
|
-
import { retryStoreAuthWithPermanentDomainError } from './auth-recovery.js';
|
|
3
|
-
import { setStoredStoreAppSession } from './session.js';
|
|
4
|
-
import { normalizeStoreFqdn } from '@shopify/cli-kit/node/context/fqdn';
|
|
5
|
-
import { randomUUID } from '@shopify/cli-kit/node/crypto';
|
|
6
|
-
import { AbortError } from '@shopify/cli-kit/node/error';
|
|
7
|
-
import { fetch } from '@shopify/cli-kit/node/http';
|
|
8
|
-
import { outputCompleted, outputContent, outputDebug, outputInfo, outputToken } from '@shopify/cli-kit/node/output';
|
|
9
|
-
import { openURL } from '@shopify/cli-kit/node/system';
|
|
10
|
-
import { createHash, randomBytes, timingSafeEqual } from 'crypto';
|
|
11
|
-
import { createServer } from 'http';
|
|
12
|
-
export function generateCodeVerifier() {
|
|
13
|
-
return randomBytes(32).toString('base64url');
|
|
14
|
-
}
|
|
15
|
-
export function computeCodeChallenge(verifier) {
|
|
16
|
-
return createHash('sha256').update(verifier).digest('base64url');
|
|
17
|
-
}
|
|
18
|
-
export function parseStoreAuthScopes(input) {
|
|
19
|
-
const scopes = input
|
|
20
|
-
.split(',')
|
|
21
|
-
.map((scope) => scope.trim())
|
|
22
|
-
.filter(Boolean);
|
|
23
|
-
if (scopes.length === 0) {
|
|
24
|
-
throw new AbortError('At least one scope is required.', 'Pass --scopes as a comma-separated list.');
|
|
25
|
-
}
|
|
26
|
-
return [...new Set(scopes)];
|
|
27
|
-
}
|
|
28
|
-
function expandImpliedStoreScopes(scopes) {
|
|
29
|
-
const expandedScopes = new Set(scopes);
|
|
30
|
-
for (const scope of scopes) {
|
|
31
|
-
const matches = scope.match(/^(unauthenticated_)?write_(.*)$/);
|
|
32
|
-
if (matches) {
|
|
33
|
-
expandedScopes.add(`${matches[1] ?? ''}read_${matches[2]}`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
return expandedScopes;
|
|
37
|
-
}
|
|
38
|
-
function resolveGrantedScopes(tokenResponse, requestedScopes) {
|
|
39
|
-
if (!tokenResponse.scope) {
|
|
40
|
-
outputDebug(outputContent `Token response did not include scope; falling back to requested scopes`);
|
|
41
|
-
return requestedScopes;
|
|
42
|
-
}
|
|
43
|
-
const grantedScopes = parseStoreAuthScopes(tokenResponse.scope);
|
|
44
|
-
const expandedGrantedScopes = expandImpliedStoreScopes(grantedScopes);
|
|
45
|
-
const missingScopes = requestedScopes.filter((scope) => !expandedGrantedScopes.has(scope));
|
|
46
|
-
if (missingScopes.length > 0) {
|
|
47
|
-
throw new AbortError('Shopify granted fewer scopes than were requested.', `Missing scopes: ${missingScopes.join(', ')}.`, [
|
|
48
|
-
'Update the app or store installation scopes.',
|
|
49
|
-
'See https://shopify.dev/app/scopes',
|
|
50
|
-
'Re-run shopify store auth.',
|
|
51
|
-
]);
|
|
52
|
-
}
|
|
53
|
-
return grantedScopes;
|
|
54
|
-
}
|
|
55
|
-
export function buildStoreAuthUrl(options) {
|
|
56
|
-
const params = new URLSearchParams();
|
|
57
|
-
params.set('client_id', STORE_AUTH_APP_CLIENT_ID);
|
|
58
|
-
params.set('scope', options.scopes.join(','));
|
|
59
|
-
params.set('redirect_uri', options.redirectUri);
|
|
60
|
-
params.set('state', options.state);
|
|
61
|
-
params.set('response_type', 'code');
|
|
62
|
-
params.set('code_challenge', options.codeChallenge);
|
|
63
|
-
params.set('code_challenge_method', 'S256');
|
|
64
|
-
return `https://${options.store}/admin/oauth/authorize?${params.toString()}`;
|
|
65
|
-
}
|
|
66
|
-
function renderAuthCallbackPage(title, message) {
|
|
67
|
-
const safeTitle = title
|
|
68
|
-
.replace(/&/g, '&')
|
|
69
|
-
.replace(/</g, '<')
|
|
70
|
-
.replace(/>/g, '>')
|
|
71
|
-
.replace(/"/g, '"');
|
|
72
|
-
const safeMessage = message
|
|
73
|
-
.replace(/&/g, '&')
|
|
74
|
-
.replace(/</g, '<')
|
|
75
|
-
.replace(/>/g, '>')
|
|
76
|
-
.replace(/"/g, '"');
|
|
77
|
-
return `<!doctype html>
|
|
78
|
-
<html lang="en">
|
|
79
|
-
<head>
|
|
80
|
-
<meta charset="utf-8" />
|
|
81
|
-
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
82
|
-
<title>${safeTitle}</title>
|
|
83
|
-
</head>
|
|
84
|
-
<body style="margin:0;background:#f6f6f7;color:#202223;font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;">
|
|
85
|
-
<main style="max-width:32rem;margin:12vh auto;padding:0 1rem;">
|
|
86
|
-
<section style="background:#fff;border:1px solid #e1e3e5;border-radius:12px;padding:1.5rem 1.25rem;box-shadow:0 1px 3px rgba(0,0,0,0.06);">
|
|
87
|
-
<h1 style="margin:0 0 0.75rem 0;font-size:1.375rem;line-height:1.2;">${safeTitle}</h1>
|
|
88
|
-
<p style="margin:0;font-size:1rem;line-height:1.5;">${safeMessage}</p>
|
|
89
|
-
</section>
|
|
90
|
-
</main>
|
|
91
|
-
</body>
|
|
92
|
-
</html>`;
|
|
93
|
-
}
|
|
94
|
-
export async function waitForStoreAuthCode({ store, state, port, timeoutMs = 5 * 60 * 1000, onListening, }) {
|
|
95
|
-
const normalizedStore = normalizeStoreFqdn(store);
|
|
96
|
-
return new Promise((resolve, reject) => {
|
|
97
|
-
let settled = false;
|
|
98
|
-
let isListening = false;
|
|
99
|
-
const timeout = setTimeout(() => {
|
|
100
|
-
settleWithError(new AbortError('Timed out waiting for OAuth callback.'));
|
|
101
|
-
}, timeoutMs);
|
|
102
|
-
const server = createServer((req, res) => {
|
|
103
|
-
const requestUrl = new URL(req.url ?? '/', `http://127.0.0.1:${port}`);
|
|
104
|
-
if (requestUrl.pathname !== STORE_AUTH_CALLBACK_PATH) {
|
|
105
|
-
res.statusCode = 404;
|
|
106
|
-
res.end('Not found');
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
const { searchParams } = requestUrl;
|
|
110
|
-
const fail = (error, tryMessage) => {
|
|
111
|
-
const abortError = typeof error === 'string' ? new AbortError(error, tryMessage) : error;
|
|
112
|
-
res.statusCode = 400;
|
|
113
|
-
res.setHeader('Content-Type', 'text/html');
|
|
114
|
-
res.setHeader('Connection', 'close');
|
|
115
|
-
res.once('finish', () => settleWithError(abortError));
|
|
116
|
-
res.end(renderAuthCallbackPage('Authentication failed', abortError.message));
|
|
117
|
-
};
|
|
118
|
-
const returnedStore = searchParams.get('shop');
|
|
119
|
-
outputDebug(outputContent `Received OAuth callback for shop ${outputToken.raw(returnedStore ?? 'unknown')}`);
|
|
120
|
-
if (!returnedStore) {
|
|
121
|
-
fail('OAuth callback store does not match the requested store.');
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
const normalizedReturnedStore = normalizeStoreFqdn(returnedStore);
|
|
125
|
-
if (normalizedReturnedStore !== normalizedStore) {
|
|
126
|
-
fail(retryStoreAuthWithPermanentDomainError(normalizedReturnedStore));
|
|
127
|
-
return;
|
|
128
|
-
}
|
|
129
|
-
const returnedState = searchParams.get('state');
|
|
130
|
-
if (!returnedState || !constantTimeEqual(returnedState, state)) {
|
|
131
|
-
fail('OAuth callback state does not match the original request.');
|
|
132
|
-
return;
|
|
133
|
-
}
|
|
134
|
-
const error = searchParams.get('error');
|
|
135
|
-
if (error) {
|
|
136
|
-
fail(`Shopify returned an OAuth error: ${error}`);
|
|
137
|
-
return;
|
|
138
|
-
}
|
|
139
|
-
const code = searchParams.get('code');
|
|
140
|
-
if (!code) {
|
|
141
|
-
fail('OAuth callback did not include an authorization code.');
|
|
142
|
-
return;
|
|
143
|
-
}
|
|
144
|
-
outputDebug(outputContent `Received authorization code ${outputToken.raw(maskToken(code))}`);
|
|
145
|
-
res.statusCode = 200;
|
|
146
|
-
res.setHeader('Content-Type', 'text/html');
|
|
147
|
-
res.setHeader('Connection', 'close');
|
|
148
|
-
res.once('finish', () => settle(() => resolve(code)));
|
|
149
|
-
res.end(renderAuthCallbackPage('Authentication succeeded', 'You can close this window and return to the terminal.'));
|
|
150
|
-
});
|
|
151
|
-
const settle = (callback) => {
|
|
152
|
-
if (settled)
|
|
153
|
-
return;
|
|
154
|
-
settled = true;
|
|
155
|
-
clearTimeout(timeout);
|
|
156
|
-
const finalize = () => {
|
|
157
|
-
callback();
|
|
158
|
-
};
|
|
159
|
-
if (!isListening) {
|
|
160
|
-
finalize();
|
|
161
|
-
return;
|
|
162
|
-
}
|
|
163
|
-
server.close(() => {
|
|
164
|
-
isListening = false;
|
|
165
|
-
finalize();
|
|
166
|
-
});
|
|
167
|
-
server.closeIdleConnections?.();
|
|
168
|
-
};
|
|
169
|
-
const settleWithError = (error) => {
|
|
170
|
-
settle(() => reject(error));
|
|
171
|
-
};
|
|
172
|
-
server.on('error', (error) => {
|
|
173
|
-
if (error.code === 'EADDRINUSE') {
|
|
174
|
-
settleWithError(new AbortError(`Port ${port} is already in use.`, `Free port ${port} and re-run ${outputToken.genericShellCommand(`shopify store auth --store ${store} --scopes <comma-separated-scopes>`).value}. Ensure that redirect URI is allowed in the app configuration.`));
|
|
175
|
-
return;
|
|
176
|
-
}
|
|
177
|
-
settleWithError(error);
|
|
178
|
-
});
|
|
179
|
-
server.listen(port, '127.0.0.1', async () => {
|
|
180
|
-
isListening = true;
|
|
181
|
-
outputDebug(outputContent `PKCE callback server listening on http://127.0.0.1:${outputToken.raw(String(port))}${outputToken.raw(STORE_AUTH_CALLBACK_PATH)}`);
|
|
182
|
-
if (!onListening)
|
|
183
|
-
return;
|
|
184
|
-
try {
|
|
185
|
-
await onListening();
|
|
186
|
-
}
|
|
187
|
-
catch (error) {
|
|
188
|
-
settleWithError(error instanceof Error ? error : new Error(String(error)));
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
function constantTimeEqual(a, b) {
|
|
194
|
-
if (a.length !== b.length)
|
|
195
|
-
return false;
|
|
196
|
-
return timingSafeEqual(Buffer.from(a, 'utf8'), Buffer.from(b, 'utf8'));
|
|
197
|
-
}
|
|
198
|
-
export async function exchangeStoreAuthCodeForToken(options) {
|
|
199
|
-
const endpoint = `https://${options.store}/admin/oauth/access_token`;
|
|
200
|
-
outputDebug(outputContent `Exchanging authorization code for token at ${outputToken.raw(endpoint)}`);
|
|
201
|
-
const response = await fetch(endpoint, {
|
|
202
|
-
method: 'POST',
|
|
203
|
-
headers: { 'Content-Type': 'application/json' },
|
|
204
|
-
body: JSON.stringify({
|
|
205
|
-
client_id: STORE_AUTH_APP_CLIENT_ID,
|
|
206
|
-
code: options.code,
|
|
207
|
-
code_verifier: options.codeVerifier,
|
|
208
|
-
redirect_uri: options.redirectUri,
|
|
209
|
-
}),
|
|
210
|
-
});
|
|
211
|
-
const body = await response.text();
|
|
212
|
-
if (!response.ok) {
|
|
213
|
-
outputDebug(outputContent `Token exchange failed with HTTP ${outputToken.raw(String(response.status))}: ${outputToken.raw(body.slice(0, 300))}`);
|
|
214
|
-
throw new AbortError(`Failed to exchange OAuth code for an access token (HTTP ${response.status}).`, body || response.statusText);
|
|
215
|
-
}
|
|
216
|
-
let parsed;
|
|
217
|
-
try {
|
|
218
|
-
parsed = JSON.parse(body);
|
|
219
|
-
}
|
|
220
|
-
catch {
|
|
221
|
-
throw new AbortError('Received an invalid token response from Shopify.');
|
|
222
|
-
}
|
|
223
|
-
outputDebug(outputContent `Token exchange succeeded: access_token=${outputToken.raw(maskToken(parsed.access_token))}, refresh_token=${outputToken.raw(parsed.refresh_token ? maskToken(parsed.refresh_token) : 'none')}, expires_in=${outputToken.raw(String(parsed.expires_in ?? 'unknown'))}s, user=${outputToken.raw(String(parsed.associated_user?.id ?? 'unknown'))} (${outputToken.raw(parsed.associated_user?.email ?? 'no email')})`);
|
|
224
|
-
return parsed;
|
|
225
|
-
}
|
|
226
|
-
const defaultStoreAuthPresenter = {
|
|
227
|
-
openingBrowser() {
|
|
228
|
-
outputInfo('Shopify CLI will open the app authorization page in your browser.');
|
|
229
|
-
outputInfo('');
|
|
230
|
-
},
|
|
231
|
-
manualAuthUrl(authorizationUrl) {
|
|
232
|
-
outputInfo('Browser did not open automatically. Open this URL manually:');
|
|
233
|
-
outputInfo(outputContent `${outputToken.link(authorizationUrl)}`);
|
|
234
|
-
outputInfo('');
|
|
235
|
-
},
|
|
236
|
-
success(store, email) {
|
|
237
|
-
const displayName = email ? ` as ${email}` : '';
|
|
238
|
-
outputCompleted('Logged in.');
|
|
239
|
-
outputCompleted(`Authenticated${displayName} against ${store}.`);
|
|
240
|
-
outputInfo('');
|
|
241
|
-
outputInfo('To verify that authentication worked, run:');
|
|
242
|
-
outputInfo(`shopify store execute --store ${store} --query 'query { shop { name id } }'`);
|
|
243
|
-
},
|
|
244
|
-
};
|
|
245
|
-
const defaultStoreAuthDependencies = {
|
|
246
|
-
openURL,
|
|
247
|
-
waitForStoreAuthCode,
|
|
248
|
-
exchangeStoreAuthCodeForToken,
|
|
249
|
-
presenter: defaultStoreAuthPresenter,
|
|
250
|
-
};
|
|
251
|
-
function createPkceBootstrap(input, exchangeCodeForToken) {
|
|
252
|
-
const store = normalizeStoreFqdn(input.store);
|
|
253
|
-
const scopes = parseStoreAuthScopes(input.scopes);
|
|
254
|
-
const port = DEFAULT_STORE_AUTH_PORT;
|
|
255
|
-
const state = randomUUID();
|
|
256
|
-
const redirectUri = storeAuthRedirectUri(port);
|
|
257
|
-
const codeVerifier = generateCodeVerifier();
|
|
258
|
-
const codeChallenge = computeCodeChallenge(codeVerifier);
|
|
259
|
-
const authorizationUrl = buildStoreAuthUrl({ store, scopes, state, redirectUri, codeChallenge });
|
|
260
|
-
outputDebug(outputContent `Starting PKCE auth for ${outputToken.raw(store)} with scopes ${outputToken.raw(scopes.join(','))} (redirect_uri=${outputToken.raw(redirectUri)})`);
|
|
261
|
-
return {
|
|
262
|
-
authorization: {
|
|
263
|
-
store,
|
|
264
|
-
scopes,
|
|
265
|
-
state,
|
|
266
|
-
port,
|
|
267
|
-
redirectUri,
|
|
268
|
-
authorizationUrl,
|
|
269
|
-
codeVerifier,
|
|
270
|
-
},
|
|
271
|
-
waitForAuthCodeOptions: {
|
|
272
|
-
store,
|
|
273
|
-
state,
|
|
274
|
-
port,
|
|
275
|
-
},
|
|
276
|
-
exchangeCodeForToken: (code) => exchangeCodeForToken({ store, code, codeVerifier, redirectUri }),
|
|
277
|
-
};
|
|
278
|
-
}
|
|
279
|
-
export async function authenticateStoreWithApp(input, dependencies = defaultStoreAuthDependencies) {
|
|
280
|
-
const bootstrap = createPkceBootstrap(input, dependencies.exchangeStoreAuthCodeForToken);
|
|
281
|
-
const { authorization: { store, scopes, redirectUri, authorizationUrl }, } = bootstrap;
|
|
282
|
-
dependencies.presenter.openingBrowser();
|
|
283
|
-
const code = await dependencies.waitForStoreAuthCode({
|
|
284
|
-
...bootstrap.waitForAuthCodeOptions,
|
|
285
|
-
onListening: async () => {
|
|
286
|
-
const opened = await dependencies.openURL(authorizationUrl);
|
|
287
|
-
if (!opened)
|
|
288
|
-
dependencies.presenter.manualAuthUrl(authorizationUrl);
|
|
289
|
-
},
|
|
290
|
-
});
|
|
291
|
-
const tokenResponse = await bootstrap.exchangeCodeForToken(code);
|
|
292
|
-
const userId = tokenResponse.associated_user?.id?.toString();
|
|
293
|
-
if (!userId) {
|
|
294
|
-
throw new AbortError('Shopify did not return associated user information for the online access token.');
|
|
295
|
-
}
|
|
296
|
-
const now = Date.now();
|
|
297
|
-
const expiresAt = tokenResponse.expires_in ? new Date(now + tokenResponse.expires_in * 1000).toISOString() : undefined;
|
|
298
|
-
setStoredStoreAppSession({
|
|
299
|
-
store,
|
|
300
|
-
clientId: STORE_AUTH_APP_CLIENT_ID,
|
|
301
|
-
userId,
|
|
302
|
-
accessToken: tokenResponse.access_token,
|
|
303
|
-
refreshToken: tokenResponse.refresh_token,
|
|
304
|
-
// Store the raw scopes returned by Shopify. Validation may treat implied
|
|
305
|
-
// write_* -> read_* permissions as satisfied, so callers should not assume
|
|
306
|
-
// session.scopes is an expanded/effective permission set.
|
|
307
|
-
scopes: resolveGrantedScopes(tokenResponse, scopes),
|
|
308
|
-
acquiredAt: new Date(now).toISOString(),
|
|
309
|
-
expiresAt,
|
|
310
|
-
refreshTokenExpiresAt: tokenResponse.refresh_token_expires_in
|
|
311
|
-
? new Date(now + tokenResponse.refresh_token_expires_in * 1000).toISOString()
|
|
312
|
-
: undefined,
|
|
313
|
-
associatedUser: tokenResponse.associated_user
|
|
314
|
-
? {
|
|
315
|
-
id: tokenResponse.associated_user.id,
|
|
316
|
-
email: tokenResponse.associated_user.email,
|
|
317
|
-
firstName: tokenResponse.associated_user.first_name,
|
|
318
|
-
lastName: tokenResponse.associated_user.last_name,
|
|
319
|
-
accountOwner: tokenResponse.associated_user.account_owner,
|
|
320
|
-
}
|
|
321
|
-
: undefined,
|
|
322
|
-
});
|
|
323
|
-
outputDebug(outputContent `Session persisted for ${outputToken.raw(store)} (user ${outputToken.raw(userId)}, expires ${outputToken.raw(expiresAt ?? 'unknown')})`);
|
|
324
|
-
dependencies.presenter.success(store, tokenResponse.associated_user?.email);
|
|
325
|
-
}
|
|
326
|
-
//# sourceMappingURL=auth.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function writeOrOutputStoreExecuteResult(result: unknown, outputFile?: string): Promise<void>;
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { writeFile } from '@shopify/cli-kit/node/fs';
|
|
2
|
-
import { outputResult } from '@shopify/cli-kit/node/output';
|
|
3
|
-
import { renderSuccess } from '@shopify/cli-kit/node/ui';
|
|
4
|
-
export async function writeOrOutputStoreExecuteResult(result, outputFile) {
|
|
5
|
-
const resultString = JSON.stringify(result, null, 2);
|
|
6
|
-
if (outputFile) {
|
|
7
|
-
await writeFile(outputFile, resultString);
|
|
8
|
-
renderSuccess({
|
|
9
|
-
headline: 'Operation succeeded.',
|
|
10
|
-
body: `Results written to ${outputFile}`,
|
|
11
|
-
});
|
|
12
|
-
}
|
|
13
|
-
else {
|
|
14
|
-
renderSuccess({ headline: 'Operation succeeded.' });
|
|
15
|
-
outputResult(resultString);
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
//# sourceMappingURL=execute-result.js.map
|