Conversation
This stack of pull requests is managed by Graphite. Learn more about stacking. |
aa2f837 to
eefef3a
Compare
ec9fc5b to
176cf3b
Compare
|
We detected some changes at Caution DO NOT create changesets for features which you do not wish to be included in the public changelog of the next CLI release. |
176cf3b to
81f77d7
Compare
| @@ -0,0 +1,132 @@ | |||
| import {normalizeStoreFqdn} from '@shopify/cli-kit/node/context/fqdn' | |||
There was a problem hiding this comment.
total nit from me: i am very against index files. they obscure intent and become a dumping ground, plus barrel files cause circular deps and tree shaking issues in many cases
There was a problem hiding this comment.
Fair nit. I’m using index.ts here as the auth module entrypoint/orchestrator rather than as a barrel export, so I’m inclined not to rename it just for this PR. If it starts turning into a grab-bag again, I’d rather fix that by tightening the module boundary than by just changing the filename.
| onListening?: () => void | Promise<void> | ||
| } | ||
|
|
||
| function renderAuthCallbackPage(title: string, message: string): string { |
There was a problem hiding this comment.
We have one view right now and I didn't want this refactor to go too far. I'm not sure if our domain needs "views" yet. But I'm noting for posterity that I would be aligned with adding this when our views increase here.
| settleWithError(new AbortError('Timed out waiting for OAuth callback.')) | ||
| }, timeoutMs) | ||
|
|
||
| const server = createServer((req, res) => { |
There was a problem hiding this comment.
odd to create a dedicated server as a closure in a callback, no?
| settleWithError(new AbortError('Timed out waiting for OAuth callback.')) | ||
| }, timeoutMs) | ||
|
|
||
| const server = createServer((req, res) => { |
There was a problem hiding this comment.
odd to create a dedicated server as a closure in a callback, no?
ryancbahan
left a comment
There was a problem hiding this comment.
I like the direction of this pr, but the seams still seem a little unclear to me. I wonder if we can invert the order of initialization a bit -- especially in callback and pkce files -- so that we first initialize the server explicitly, initialize the persistence stores, establish the dynamic route(s) that need to be hit, and then let the callback chain(s) flow.
| success: (store: string, email?: string) => void | ||
| } | ||
|
|
||
| interface StoreAuthDependencies { |
There was a problem hiding this comment.
I don't know that the DI pattern here is particularly serving us
There was a problem hiding this comment.
That's fair, it's unique to this flow and somewhat unusual in the codebase. It wasn't bothering me in the original implementation because the flow is bounded, but this version of the implementation isn't necessarily as clear. I'll see what the alternative looks like.
There was a problem hiding this comment.
I've adjusted the implementation to consolidate the DI object + make it authoritative. That'll make it easier to refactor out later, which I'm not opposed to doing.
I looked at whether there was a smaller callback extraction that would materially clarify ownership here without turning into a larger redesign. The only bounded version I found was splitting server lifecycle from callback request handling, but it didn’t feel like enough improvement to justify more churn in this PR after the other seam cleanups. So I’d keep the larger callback/pkce lifecycle inversion as follow-up work rather than half-landing it here. |
81f77d7 to
d2680ce
Compare
eefef3a to
b38f61c
Compare

What
Restructure
shopify store authunderpackages/cli/src/cli/services/store/auth/and split the main auth responsibilities into explicit auth-domain seams.This keeps the command contract the same while making auth ownership easier to review and build on.
Why
The store auth fast-follow landed quickly and left auth responsibilities spread across a few files with blurry ownership.
That made it harder to reason about:
It also made the execute-side follow-up harder to stage cleanly.
The goal here is to make the auth domain legible on its own before building the execute-side cleanup on top.
How
This PR moves auth code under
services/store/auth/and separates:auth/index.ts— auth orchestrationauth/session-store.ts— local session bucket storage and current-user selectionauth/session-lifecycle.ts— expiry / refresh / invalidation policyauth/token-client.ts— auth-related HTTPauth/config.ts/auth/recovery.ts— shared auth support codeIt also:
getCurrentStoredStoreAppSession(...)so current-user semantics are explicitHigh-level ownership after this PR:
This PR is intentionally auth-only. The execute-side folder move and full execute-context cleanup stay in the next stacked PR.
Testing
Manual checks:
pnpm run shopify store auth --store donaldmerand.myshopify.com --scopes read_products pnpm run shopify store execute --store donaldmerand.myshopify.com --query 'query { shop { name id } }' node packages/cli/bin/run.js store auth --help node packages/cli/bin/run.js store execute --helpVerify that:
store authstill authenticates and persists store auth successfullystore executestill reuses stored auth successfullyConsidered
persistence/transportfolders: rejected in favor of domain-firststore/authownership.Measuring impact
Checklist