@tenderprompt/cli 0.1.30 → 0.1.31
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/index.js +65 -17
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2037,8 +2037,38 @@ function normalizeStoredProfile(value) {
|
|
|
2037
2037
|
permissions: Array.isArray(record.permissions)
|
|
2038
2038
|
? record.permissions.filter((permission) => typeof permission === 'string')
|
|
2039
2039
|
: undefined,
|
|
2040
|
+
...normalizeStoredShopifyContext(record),
|
|
2040
2041
|
};
|
|
2041
2042
|
}
|
|
2043
|
+
function normalizeStoredShopifyContext(record) {
|
|
2044
|
+
const shopifyAppUrl = typeof record.shopifyAppUrl === 'string' ? record.shopifyAppUrl : null;
|
|
2045
|
+
if (shopifyAppUrl) {
|
|
2046
|
+
try {
|
|
2047
|
+
const parsed = parseShopifyAppUrl(shopifyAppUrl, 'profile.shopifyAppUrl');
|
|
2048
|
+
return {
|
|
2049
|
+
shopifyAppUrl: parsed.appUrl,
|
|
2050
|
+
shopifyStore: parsed.store,
|
|
2051
|
+
};
|
|
2052
|
+
}
|
|
2053
|
+
catch {
|
|
2054
|
+
return {};
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
const shopifyStore = typeof record.shopifyStore === 'string' ? record.shopifyStore : null;
|
|
2058
|
+
if (shopifyStore) {
|
|
2059
|
+
try {
|
|
2060
|
+
const store = parseShopifyStoreHandle(shopifyStore, 'profile.shopifyStore');
|
|
2061
|
+
return {
|
|
2062
|
+
shopifyAppUrl: shopifyAppUrlForStore(store),
|
|
2063
|
+
shopifyStore: store,
|
|
2064
|
+
};
|
|
2065
|
+
}
|
|
2066
|
+
catch {
|
|
2067
|
+
return {};
|
|
2068
|
+
}
|
|
2069
|
+
}
|
|
2070
|
+
return {};
|
|
2071
|
+
}
|
|
2042
2072
|
function normalizeConfig(value) {
|
|
2043
2073
|
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
2044
2074
|
return {};
|
|
@@ -2148,20 +2178,19 @@ function parseShopifyStoreHandle(value, flag) {
|
|
|
2148
2178
|
function shopifyAppUrlForStore(store) {
|
|
2149
2179
|
return `https://admin.shopify.com/store/${store}/apps/tender-prompt/shopify`;
|
|
2150
2180
|
}
|
|
2151
|
-
function
|
|
2152
|
-
const value = args[index + 1];
|
|
2181
|
+
function parseShopifyAppUrl(value, flag) {
|
|
2153
2182
|
if (!value || value.startsWith('-')) {
|
|
2154
|
-
throw new TenderCliUsageError(
|
|
2183
|
+
throw new TenderCliUsageError(`${flag} requires a Shopify Admin App Home URL.`);
|
|
2155
2184
|
}
|
|
2156
2185
|
let url;
|
|
2157
2186
|
try {
|
|
2158
2187
|
url = new URL(value);
|
|
2159
2188
|
}
|
|
2160
2189
|
catch {
|
|
2161
|
-
throw new TenderCliUsageError(
|
|
2190
|
+
throw new TenderCliUsageError(`${flag} requires a valid Shopify Admin App Home URL.`);
|
|
2162
2191
|
}
|
|
2163
2192
|
if (url.protocol !== 'https:' || url.hostname !== 'admin.shopify.com') {
|
|
2164
|
-
throw new TenderCliUsageError(
|
|
2193
|
+
throw new TenderCliUsageError(`${flag} must start with https://admin.shopify.com/.`);
|
|
2165
2194
|
}
|
|
2166
2195
|
const parts = url.pathname.split('/').filter(Boolean);
|
|
2167
2196
|
const deviceSuffix = parts[5] === 'device' ? parts[5] : null;
|
|
@@ -2169,20 +2198,26 @@ function parseShopifyAppUrlFlag(args, index) {
|
|
|
2169
2198
|
parts[0] !== 'store' ||
|
|
2170
2199
|
parts[2] !== 'apps' ||
|
|
2171
2200
|
parts[4] !== 'shopify') {
|
|
2172
|
-
throw new TenderCliUsageError(
|
|
2201
|
+
throw new TenderCliUsageError(`${flag} must look like https://admin.shopify.com/store/<store>/apps/tender-prompt/shopify.`);
|
|
2173
2202
|
}
|
|
2174
2203
|
if (url.search || url.hash) {
|
|
2175
|
-
throw new TenderCliUsageError(
|
|
2204
|
+
throw new TenderCliUsageError(`${flag} should not include a query string or hash.`);
|
|
2176
2205
|
}
|
|
2177
|
-
const store = parseShopifyStoreHandle(parts[1],
|
|
2178
|
-
const appHandle = parseShopifyStoreHandle(parts[3],
|
|
2206
|
+
const store = parseShopifyStoreHandle(parts[1], flag);
|
|
2207
|
+
const appHandle = parseShopifyStoreHandle(parts[3], flag);
|
|
2179
2208
|
return {
|
|
2180
2209
|
store,
|
|
2181
2210
|
appUrl: `https://admin.shopify.com/store/${store}/apps/${appHandle}/shopify`,
|
|
2182
2211
|
};
|
|
2183
2212
|
}
|
|
2213
|
+
function parseShopifyAppUrlFlag(args, index) {
|
|
2214
|
+
return parseShopifyAppUrl(args[index + 1], '--shopify-app-url');
|
|
2215
|
+
}
|
|
2216
|
+
function shopifyDeviceVerificationUri(shopifyAppUrl) {
|
|
2217
|
+
return `${shopifyAppUrl.replace(/\/+$/, '')}/device`;
|
|
2218
|
+
}
|
|
2184
2219
|
function shopifyDeviceVerificationUrl(input) {
|
|
2185
|
-
return `${input.shopifyAppUrl
|
|
2220
|
+
return `${shopifyDeviceVerificationUri(input.shopifyAppUrl)}?user_code=${encodeURIComponent(input.userCode)}`;
|
|
2186
2221
|
}
|
|
2187
2222
|
function parseTokenFlag(args, index) {
|
|
2188
2223
|
const value = args[index + 1];
|
|
@@ -8226,6 +8261,8 @@ async function runAuthStatus(command, io, runtime) {
|
|
|
8226
8261
|
artifactId: profile?.artifactId ?? null,
|
|
8227
8262
|
permissions: profile?.permissions ?? [],
|
|
8228
8263
|
expiresAt: formatExpiry(profile?.expiresAt),
|
|
8264
|
+
shopifyAppUrl: profile?.shopifyAppUrl ?? null,
|
|
8265
|
+
shopifyStore: profile?.shopifyStore ?? null,
|
|
8229
8266
|
};
|
|
8230
8267
|
if (command.json) {
|
|
8231
8268
|
io.stdout(JSON.stringify(result, null, 2));
|
|
@@ -8240,6 +8277,7 @@ async function runAuthStatus(command, io, runtime) {
|
|
|
8240
8277
|
`app_id: ${profile.artifactId ?? '(account)'}`,
|
|
8241
8278
|
`permissions: ${(profile.permissions ?? []).join(' ') || '(unknown)'}`,
|
|
8242
8279
|
`expires_at: ${formatExpiry(profile.expiresAt) ?? '(unknown)'}`,
|
|
8280
|
+
`shopify_app_url: ${profile.shopifyAppUrl ?? '(none)'}`,
|
|
8243
8281
|
].join('\n'));
|
|
8244
8282
|
}
|
|
8245
8283
|
else {
|
|
@@ -8284,6 +8322,8 @@ async function runAuthStatus(command, io, runtime) {
|
|
|
8284
8322
|
artifactId: profile?.artifactId ?? null,
|
|
8285
8323
|
permissions: profile?.permissions ?? [],
|
|
8286
8324
|
expiresAt: formatExpiry(profile?.expiresAt),
|
|
8325
|
+
shopifyAppUrl: profile?.shopifyAppUrl ?? null,
|
|
8326
|
+
shopifyStore: profile?.shopifyStore ?? null,
|
|
8287
8327
|
};
|
|
8288
8328
|
if (command.json) {
|
|
8289
8329
|
io.stdout(JSON.stringify(result, null, 2));
|
|
@@ -8298,6 +8338,7 @@ async function runAuthStatus(command, io, runtime) {
|
|
|
8298
8338
|
`app_id: ${profile.artifactId ?? '(account)'}`,
|
|
8299
8339
|
`permissions: ${(profile.permissions ?? []).join(' ') || '(unknown)'}`,
|
|
8300
8340
|
`expires_at: ${formatExpiry(profile.expiresAt) ?? '(unknown)'}`,
|
|
8341
|
+
`shopify_app_url: ${profile.shopifyAppUrl ?? '(none)'}`,
|
|
8301
8342
|
].join('\n'));
|
|
8302
8343
|
}
|
|
8303
8344
|
else {
|
|
@@ -8314,7 +8355,11 @@ async function runAuthLogin(command, io, runtime) {
|
|
|
8314
8355
|
const fetcher = runtime.fetcher ?? fetch;
|
|
8315
8356
|
const sleeper = runtime.sleeper ?? ((milliseconds) => new Promise((resolve) => setTimeout(resolve, milliseconds)));
|
|
8316
8357
|
const now = runtime.now ?? Date.now;
|
|
8317
|
-
const
|
|
8358
|
+
const config = await readConfig(env);
|
|
8359
|
+
const existingProfile = config.profiles?.[command.saveProfile] ?? null;
|
|
8360
|
+
const baseUrl = command.baseUrl ?? existingProfile?.baseUrl ?? readDefaultBaseUrl(env);
|
|
8361
|
+
const shopifyAppUrl = command.shopifyAppUrl ?? existingProfile?.shopifyAppUrl ?? null;
|
|
8362
|
+
const shopifyStore = command.shopifyStore ?? existingProfile?.shopifyStore ?? null;
|
|
8318
8363
|
const deviceResponse = await fetcher(`${baseUrl}/oauth/device/code`, {
|
|
8319
8364
|
method: 'POST',
|
|
8320
8365
|
headers: {
|
|
@@ -8330,19 +8375,19 @@ async function runAuthLogin(command, io, runtime) {
|
|
|
8330
8375
|
if (!deviceResponse.ok || !devicePayload?.device_code || !devicePayload.user_code || !devicePayload.verification_uri_complete) {
|
|
8331
8376
|
throw new Error(devicePayload?.error_description ?? devicePayload?.error ?? `Device authorization failed with HTTP ${deviceResponse.status}.`);
|
|
8332
8377
|
}
|
|
8333
|
-
const verificationUriComplete =
|
|
8378
|
+
const verificationUriComplete = shopifyAppUrl
|
|
8334
8379
|
? shopifyDeviceVerificationUrl({
|
|
8335
|
-
shopifyAppUrl
|
|
8380
|
+
shopifyAppUrl,
|
|
8336
8381
|
userCode: devicePayload.user_code,
|
|
8337
8382
|
})
|
|
8338
8383
|
: devicePayload.verification_uri_complete;
|
|
8339
|
-
const verificationUri =
|
|
8384
|
+
const verificationUri = shopifyAppUrl ? shopifyDeviceVerificationUri(shopifyAppUrl) : devicePayload.verification_uri;
|
|
8340
8385
|
const pendingResult = {
|
|
8341
8386
|
ok: true,
|
|
8342
8387
|
command: command.command,
|
|
8343
8388
|
baseUrl,
|
|
8344
|
-
shopifyAppUrl
|
|
8345
|
-
shopifyStore
|
|
8389
|
+
shopifyAppUrl,
|
|
8390
|
+
shopifyStore,
|
|
8346
8391
|
profile: command.tokenProfile,
|
|
8347
8392
|
saveProfile: command.saveProfile,
|
|
8348
8393
|
userCode: devicePayload.user_code,
|
|
@@ -8383,7 +8428,6 @@ async function runAuthLogin(command, io, runtime) {
|
|
|
8383
8428
|
});
|
|
8384
8429
|
const tokenPayload = await parseJsonResponse(tokenResponse);
|
|
8385
8430
|
if (tokenResponse.ok && tokenPayload?.access_token) {
|
|
8386
|
-
const config = await readConfig(env);
|
|
8387
8431
|
const profiles = config.profiles ?? {};
|
|
8388
8432
|
profiles[command.saveProfile] = {
|
|
8389
8433
|
baseUrl,
|
|
@@ -8393,6 +8437,8 @@ async function runAuthLogin(command, io, runtime) {
|
|
|
8393
8437
|
artifactId: tokenPayload.artifact_id,
|
|
8394
8438
|
expiresAt: tokenPayload.expires_at,
|
|
8395
8439
|
permissions: splitScope(tokenPayload.scope),
|
|
8440
|
+
...(shopifyAppUrl ? { shopifyAppUrl } : {}),
|
|
8441
|
+
...(shopifyStore ? { shopifyStore } : {}),
|
|
8396
8442
|
};
|
|
8397
8443
|
await writeConfig(env, {
|
|
8398
8444
|
...config,
|
|
@@ -8410,6 +8456,8 @@ async function runAuthLogin(command, io, runtime) {
|
|
|
8410
8456
|
artifactId: tokenPayload.artifact_id ?? null,
|
|
8411
8457
|
permissions: splitScope(tokenPayload.scope),
|
|
8412
8458
|
expiresAt: formatExpiry(tokenPayload.expires_at),
|
|
8459
|
+
shopifyAppUrl,
|
|
8460
|
+
shopifyStore,
|
|
8413
8461
|
configPath: readConfigPath(env),
|
|
8414
8462
|
};
|
|
8415
8463
|
if (command.json) {
|