Repository navigation
Add typed JSON output to auth logout - #8790
Conversation
|
/snapit |
|
🫰✨ Thanks @isaacroldan! Your snapshot has been published to npm. Built from Test the snapshot by installing your package globally: pnpm i -g --@shopify:registry=https://registry.npmjs.org @shopify/cli@0.0.0-snapshot-20261006105407Caution After installing, validate the version by running |
|
/snapit |
|
🫰✨ Thanks @isaacroldan! Your snapshot has been published to npm. Built from Test the snapshot by installing your package globally: pnpm i -g --@shopify:registry=https://registry.npmjs.org @shopify/cli@0.0.0-snapshot-20261006112512Caution After installing, validate the version by running |
1c8badc to
0b915be
Compare
Differences in type declarationsWe detected differences in the type declarations generated by Typescript for this branch compared to the baseline ('main' branch). Please, review them to ensure they are backward-compatible. Here are some important things to keep in mind:
New type declarationsWe found no new type declarations in this PR Existing type declarationspackages/cli-kit/dist/public/node/session-prompt.d.ts@@ -1,3 +1,12 @@
+/** Public account details for a selected Shopify identity session. */
+export interface SelectedSession {
+ /** The identity provider user ID. */
+ userId: string;
+ /** The alias or display label used to select the account. */
+ alias: string;
+ /** The email returned by authentication, or null when it is not stored. */
+ email: string | null;
+}
/**
* Prompts the user to select from existing sessions or log in with a different account.
*
@@ -7,4 +16,11 @@
* @param alias - Optional alias of the account to switch to.
* @returns Promise with the alias of the chosen session.
*/
-export declare function promptSessionSelect(alias?: string): Promise<string>;
\ No newline at end of file
+export declare function promptSessionSelect(alias?: string): Promise<string>;
+/**
+ * Selects an existing session or authenticates a new account and returns its public details.
+ *
+ * @param alias - Optional alias or user ID of an account to select.
+ * @returns The selected user ID, display alias, and stored email without credentials.
+ */
+export declare function promptSessionSelectWithDetails(alias?: string): Promise<SelectedSession>;
\ No newline at end of file
packages/cli-kit/dist/private/node/session/schema.d.ts@@ -9,6 +9,7 @@ declare const IdentityTokenSchema: zod.ZodObject<{
scopes: zod.ZodArray<zod.ZodString, "many">;
userId: zod.ZodString;
alias: zod.ZodOptional<zod.ZodString>;
+ email: zod.ZodOptional<zod.ZodString>;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
refreshToken: string;
@@ -16,6 +17,7 @@ declare const IdentityTokenSchema: zod.ZodObject<{
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
}, {
accessToken: string;
refreshToken: string;
@@ -23,6 +25,7 @@ declare const IdentityTokenSchema: zod.ZodObject<{
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
}>;
/**
* The schema represents an application token.
@@ -51,6 +54,7 @@ declare const SessionSchema: zod.ZodObject<{
scopes: zod.ZodArray<zod.ZodString, "many">;
userId: zod.ZodString;
alias: zod.ZodOptional<zod.ZodString>;
+ email: zod.ZodOptional<zod.ZodString>;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
refreshToken: string;
@@ -58,6 +62,7 @@ declare const SessionSchema: zod.ZodObject<{
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
}, {
accessToken: string;
refreshToken: string;
@@ -65,6 +70,7 @@ declare const SessionSchema: zod.ZodObject<{
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
}>;
applications: zod.ZodObject<{}, "strip", zod.ZodObject<{
accessToken: zod.ZodString;
@@ -120,6 +126,7 @@ declare const SessionSchema: zod.ZodObject<{
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -137,6 +144,7 @@ declare const SessionSchema: zod.ZodObject<{
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -183,6 +191,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
scopes: zod.ZodArray<zod.ZodString, "many">;
userId: zod.ZodString;
alias: zod.ZodOptional<zod.ZodString>;
+ email: zod.ZodOptional<zod.ZodString>;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
refreshToken: string;
@@ -190,6 +199,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
}, {
accessToken: string;
refreshToken: string;
@@ -197,6 +207,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
}>;
applications: zod.ZodObject<{}, "strip", zod.ZodObject<{
accessToken: zod.ZodString;
@@ -252,6 +263,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -269,6 +281,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -286,6 +299,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
scopes: zod.ZodArray<zod.ZodString, "many">;
userId: zod.ZodString;
alias: zod.ZodOptional<zod.ZodString>;
+ email: zod.ZodOptional<zod.ZodString>;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
refreshToken: string;
@@ -293,6 +307,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
}, {
accessToken: string;
refreshToken: string;
@@ -300,6 +315,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
}>;
applications: zod.ZodObject<{}, "strip", zod.ZodObject<{
accessToken: zod.ZodString;
@@ -355,6 +371,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -372,6 +389,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -389,6 +407,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
scopes: zod.ZodArray<zod.ZodString, "many">;
userId: zod.ZodString;
alias: zod.ZodOptional<zod.ZodString>;
+ email: zod.ZodOptional<zod.ZodString>;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
refreshToken: string;
@@ -396,6 +415,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
}, {
accessToken: string;
refreshToken: string;
@@ -403,6 +423,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
}>;
applications: zod.ZodObject<{}, "strip", zod.ZodObject<{
accessToken: zod.ZodString;
@@ -458,6 +479,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -475,6 +497,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -492,6 +515,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
scopes: zod.ZodArray<zod.ZodString, "many">;
userId: zod.ZodString;
alias: zod.ZodOptional<zod.ZodString>;
+ email: zod.ZodOptional<zod.ZodString>;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
refreshToken: string;
@@ -499,6 +523,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
}, {
accessToken: string;
refreshToken: string;
@@ -506,6 +531,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
}>;
applications: zod.ZodObject<{}, "strip", zod.ZodObject<{
accessToken: zod.ZodString;
@@ -561,6 +587,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -578,6 +605,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -595,6 +623,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
scopes: zod.ZodArray<zod.ZodString, "many">;
userId: zod.ZodString;
alias: zod.ZodOptional<zod.ZodString>;
+ email: zod.ZodOptional<zod.ZodString>;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
refreshToken: string;
@@ -602,6 +631,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
}, {
accessToken: string;
refreshToken: string;
@@ -609,6 +639,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
}>;
applications: zod.ZodObject<{}, "strip", zod.ZodObject<{
accessToken: zod.ZodString;
@@ -664,6 +695,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -681,6 +713,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -698,6 +731,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
scopes: zod.ZodArray<zod.ZodString, "many">;
userId: zod.ZodString;
alias: zod.ZodOptional<zod.ZodString>;
+ email: zod.ZodOptional<zod.ZodString>;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
refreshToken: string;
@@ -705,6 +739,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
}, {
accessToken: string;
refreshToken: string;
@@ -712,6 +747,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
}>;
applications: zod.ZodObject<{}, "strip", zod.ZodObject<{
accessToken: zod.ZodString;
@@ -767,6 +803,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -784,6 +821,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -801,6 +839,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
scopes: zod.ZodArray<zod.ZodString, "many">;
userId: zod.ZodString;
alias: zod.ZodOptional<zod.ZodString>;
+ email: zod.ZodOptional<zod.ZodString>;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
refreshToken: string;
@@ -808,6 +847,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
}, {
accessToken: string;
refreshToken: string;
@@ -815,6 +855,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
}>;
applications: zod.ZodObject<{}, "strip", zod.ZodObject<{
accessToken: zod.ZodString;
@@ -870,6 +911,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -887,6 +929,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -904,6 +947,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
scopes: zod.ZodArray<zod.ZodString, "many">;
userId: zod.ZodString;
alias: zod.ZodOptional<zod.ZodString>;
+ email: zod.ZodOptional<zod.ZodString>;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
refreshToken: string;
@@ -911,6 +955,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
}, {
accessToken: string;
refreshToken: string;
@@ -918,6 +963,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
}>;
applications: zod.ZodObject<{}, "strip", zod.ZodObject<{
accessToken: zod.ZodString;
@@ -973,6 +1019,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -990,6 +1037,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -1007,6 +1055,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
scopes: zod.ZodArray<zod.ZodString, "many">;
userId: zod.ZodString;
alias: zod.ZodOptional<zod.ZodString>;
+ email: zod.ZodOptional<zod.ZodString>;
}, "strip", zod.ZodTypeAny, {
accessToken: string;
refreshToken: string;
@@ -1014,6 +1063,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
}, {
accessToken: string;
refreshToken: string;
@@ -1021,6 +1071,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
}>;
applications: zod.ZodObject<{}, "strip", zod.ZodObject<{
accessToken: zod.ZodString;
@@ -1076,6 +1127,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
expiresAt: Date;
userId: string;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
@@ -1093,6 +1145,7 @@ export declare const SessionsSchema: zod.ZodObject<{}, "strip", zod.ZodObject<{}
userId: string;
expiresAt?: unknown;
alias?: string | undefined;
+ email?: string | undefined;
};
applications: {} & {
[k: string]: {
packages/cli-kit/dist/private/node/session/store.d.ts@@ -1,4 +1,5 @@
-import type { Sessions } from './schema.js';
+import type { IdentityToken, Sessions } from './schema.js';
+type SessionAccount = Pick<IdentityToken, 'userId' | 'alias' | 'email'>;
/**
* Serializes the session as a JSON and stores it in the system.
* @param session - the session to store.
@@ -15,12 +16,12 @@ export declare function fetch(): Promise<Sessions | undefined>;
*/
export declare function remove(): Promise<void>;
/**
- * Gets the session alias for a given user ID.
+ * Gets public account details for a stored user ID.
*
- * @param userId - The user ID of the session to get the alias for.
- * @returns The alias for the session if it exists, otherwise undefined.
+ * @param userId - The stored user ID whose account details are requested.
+ * @returns The account details if the session exists, otherwise undefined.
*/
-export declare function getSessionAlias(userId: string): Promise<string | undefined>;
+export declare function getSessionAccount(userId: string): Promise<SessionAccount | undefined>;
/**
* Sets the alias for a given user's session and persists it.
*
@@ -34,4 +35,6 @@ export declare function setSessionAlias(userId: string, alias: string): Promise<
* @param alias - The alias to search for
* @returns The user ID if found, otherwise undefined
*/
-export declare function findSessionByAlias(alias: string): Promise<string | undefined>;
\ No newline at end of file
+export declare function findSessionByAlias(alias: string): Promise<string | undefined>;
+export declare function findSessionAccountByAlias(alias: string): Promise<SessionAccount | undefined>;
+export {};
\ No newline at end of file
|
|
/snapit |
|
🫰✨ Thanks @isaacroldan! Your snapshot has been published to npm. Built from Test the snapshot by installing your package globally: pnpm i -g --@shopify:registry=https://registry.npmjs.org @shopify/cli@0.0.0-snapshot-20261006115508Caution After installing, validate the version by running |
0b915be to
c7ba508
Compare
|
/snapit |
|
🫰✨ Thanks @isaacroldan! Your snapshot has been published to npm. Built from Test the snapshot by installing your package globally: pnpm i -g --@shopify:registry=https://registry.npmjs.org @shopify/cli@0.0.0-snapshot-20261006121211Caution After installing, validate the version by running |
c7ba508 to
554ba09
Compare
|
/snapit |
|
🫰✨ Thanks @isaacroldan! Your snapshot has been published to npm. Built from Test the snapshot by installing your package globally: pnpm i -g --@shopify:registry=https://registry.npmjs.org @shopify/cli@0.0.0-snapshot-20261006151258Caution After installing, validate the version by running |
554ba09 to
de2c568
Compare
|
/snapit |
|
🫰✨ Thanks @isaacroldan! Your snapshot has been published to npm. Built from Test the snapshot by installing your package globally: pnpm i -g --@shopify:registry=https://registry.npmjs.org @shopify/cli@0.0.0-snapshot-20261006165737Caution After installing, validate the version by running |
amcaplan
left a comment
There was a problem hiding this comment.
Code looks good, I'm assuming it's been tophatted appropriately. I do think some shared testing utils will go a long way in keeping these PRs tighter and more consistent.
| mockAndCaptureOutput().clear() | ||
| }) | ||
|
|
||
| test.each(['--json', '-j'])('writes one completed result through the launcher with %s', async (flag) => { |
There was a problem hiding this comment.
Some of these tests seem like they could be shared somewhere - like have an isValidJsonCommand(command, ...workingFlagSet) function somewhere which runs the basic tests in a generalizable way rather than rewriting all the tests for each command.
There was a problem hiding this comment.
Good point, i'll take a look at that and probably update it in a future PR
WHY are these changes introduced?
Let scripts read the logout result without parsing terminal messages.
WHAT is this pull request doing?
Add
--json/-jand a result schema directly to the existing command. Return{"status":"success"}after logout completes. Keep the existing text output and session cleanup.Validation: 15 focused tests, lint and build pass.
How to manually test your changes?
Use this PR's CLI or snapshot. Logout clears all stored CLI sessions.
shopify auth logout --json-schemawhile signed in. Expect a schema; selecting a stored alias withshopify auth login --alias "<account-alias>" --no-inputmust still work.shopify auth logout --json > auth-logout.json 2> auth-logout.stderr. Expect one{"status":"success"}object in the result file, with no success banner. Selecting the old alias with--no-inputmust now fail.shopify auth logout -jagain. Expect the same result when no sessions remain.shopify auth logout. Expect✅ Success! Logged out from all the accounts.on stderr and no stdout output.Checklist
Stack: #8790: logout JSON → #8791: login JSON → #8794: account details. Merge in this order.