Skip to content

Add shopify store create trial command#7346

Open
tizmagik wants to merge 1 commit intomainfrom
jg/store-create-trial
Open

Add shopify store create trial command#7346
tizmagik wants to merge 1 commit intomainfrom
jg/store-create-trial

Conversation

@tizmagik
Copy link
Copy Markdown

Summary

  • Adds shopify store create trial — a non-interactive way to create a Shopify trial store from the CLI, backed by the Signups API StoreCreate mutation.
  • Adds the cli-kit Signups foundation: shop-create OAuth scope, signupsApi application + ensureAuthenticatedSignups, signupsFqdn(), and a signupsRequest API helper.
  • Lands the command in @shopify/store (picks up the recent extraction).

Supersedes #7218, which targeted the pre-extraction layout and used a flag-based shape (store create --dev). This PR uses the subcommand shape (store create trial) so sibling commands (e.g. dev stores) can slot in as additional subcommands.

Command shape

shopify store create trial [--name <name>] [--subdomain <sub>] [--country US] [--json]

All flags have env-var equivalents (SHOPIFY_FLAG_STORE_NAME, SHOPIFY_FLAG_STORE_SUBDOMAIN, SHOPIFY_FLAG_STORE_COUNTRY). --country defaults to US.

Test plan

  • pnpm --filter @shopify/store vitest run — all new unit tests pass (15 tests across command + service)
  • pnpm build — monorepo builds cleanly (cli-kit → store → cli)
  • Manual: ./packages/cli/bin/run store create trial --name "Plan Test Store" creates a trial store and prints next steps
  • Manual: ./packages/cli/bin/run store create trial --json emits parseable JSON on stdout
  • Manual: ./packages/cli/bin/run store create trial --subdomain taken surfaces user errors from the Signups API
  • CI: manifests, README, dev docs, and E2E commands.txt snapshot all regenerated from a cold install

🤖 Generated with Claude Code

@tizmagik tizmagik requested review from a team as code owners April 17, 2026 19:53
Copilot AI review requested due to automatic review settings April 17, 2026 19:53
@tizmagik tizmagik mentioned this pull request Apr 17, 2026
5 tasks
@tizmagik tizmagik force-pushed the jg/store-create-trial branch from 80db198 to c3be9fc Compare April 17, 2026 19:54
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR introduces a new non-interactive shopify store create trial command in @shopify/store, backed by the Signups API storeCreate mutation, and adds the necessary cli-kit auth + API foundations to call Signups using an Identity bearer token.

Changes:

  • Add shopify store create trial command + service layer to create a trial store and optionally output JSON.
  • Add cli-kit Signups support: shop-create scope transform, signupsApi auth path (ensureAuthenticatedSignups), signupsFqdn(), and signupsRequest() helper.
  • Regenerate CLI manifests/docs/snapshots to expose the new command.

Reviewed changes

Copilot reviewed 18 out of 18 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
packages/store/src/index.ts Registers the new store:create:trial command.
packages/store/src/cli/services/store/create/index.ts Implements Signups storeCreate call + error handling.
packages/store/src/cli/services/store/create/index.test.ts Adds unit coverage for store creation service behavior and error cases.
packages/store/src/cli/commands/store/create/trial.ts Adds the CLI command/flags and output behavior (--json vs UI).
packages/store/src/cli/commands/store/create/trial.test.ts Adds unit tests for flag plumbing and output paths.
packages/e2e/data/snapshots/commands.txt Updates command tree snapshot to include store create trial.
packages/cli/oclif.manifest.json Adds the new command to the generated oclif manifest.
packages/cli/README.md Documents the new command usage and flags.
packages/cli-kit/src/public/node/session.ts Adds ensureAuthenticatedSignups() for Signups API auth.
packages/cli-kit/src/public/node/context/fqdn.ts Adds signupsFqdn() resolver for Signups service routing.
packages/cli-kit/src/public/node/api/signups.ts Adds signupsRequest() GraphQL helper targeting /services/signups/graphql.
packages/cli-kit/src/public/node/api/signups.test.ts Adds unit tests ensuring correct graphqlRequest wiring for Signups.
packages/cli-kit/src/private/node/session/scopes.ts Adds shop-createhttps://api.shopify.com/auth/shop.create transform.
packages/cli-kit/src/private/node/session/scopes.test.ts Adds test for the new scope transform.
packages/cli-kit/src/private/node/session.ts Adds signupsApi application handling and exposes identity token when requested.
docs-shopify.dev/commands/store-create-trial.doc.ts Adds autogenerated public docs entry for the command.
docs-shopify.dev/commands/interfaces/store-create-trial.interface.ts Adds autogenerated flags interface for docs generation.
docs-shopify.dev/commands/examples/store-create-trial.example.sh Adds autogenerated example snippet.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +287 to +300
export async function ensureAuthenticatedSignups(
scopes: SignupsScope[] = ['shop-create'],
env = process.env,
options: EnsureAuthenticatedAdditionalOptions = {},
): Promise<{token: string; userId: string}> {
outputDebug(outputContent`Ensuring that the user is authenticated with the Signups API with the following scopes:
${outputToken.json(scopes)}
`)
const tokens = await ensureAuthenticated({signupsApi: {scopes}}, env, options)
if (!tokens.identity) {
throw new BugError('No identity token found after ensuring authenticated')
}
return {token: tokens.identity, userId: tokens.userId}
}
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add unit tests for ensureAuthenticatedSignups similar to the existing ensureAuthenticatedPartners/ensureAuthenticatedAdmin tests. This function introduces new authentication behavior (default scopes, token selection, and the No identity token found... error path) but currently has no direct coverage in packages/cli-kit/src/public/node/session.test.ts.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

@tizmagik tizmagik Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added ensureAuthenticatedSignups coverage in session.test.ts: default scope, custom scope passthrough, success, and the No identity token error path.

Comment on lines +110 to +118
export async function signupsFqdn(): Promise<string> {
const environment = serviceEnvironment()
const productionFqdn = 'shopify.com'
switch (environment) {
case 'local':
return new DevServerCore().host('shopify')
default:
return productionFqdn
}
Copy link

Copilot AI Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add coverage for signupsFqdn() in fqdn.test.ts (local vs production), like the existing tests for partnersFqdn, adminFqdn, etc. Without a direct test, regressions in the Signups FQDN routing (especially the local dev-server host mapping) may go unnoticed.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added a describe('signupsFqdn') block in fqdn.test.ts covering local + production environments, matching the pattern used by partnersFqdn / adminFqdn.

Adds a programmatic way to create a Shopify trial store from the CLI,
backed by the Signups API's StoreCreate mutation.

- Registers `store:create:trial` in @shopify/store with flags for
  --name, --subdomain, --country (default US), and --json.
- Adds cli-kit Signups foundation: `shop-create` OAuth scope,
  `signupsApi` application + `ensureAuthenticatedSignups`,
  `signupsFqdn()`, and `signupsRequest` API helper.
- Regenerates oclif manifest, README, dev docs, and e2e snapshot.

Supersedes #7218.
@tizmagik tizmagik force-pushed the jg/store-create-trial branch from c3be9fc to 4ca00ba Compare April 17, 2026 20:02
@github-actions
Copy link
Copy Markdown
Contributor

Differences in type declarations

We 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:

  • Some seemingly private modules might be re-exported through public modules.
  • If the branch is behind main you might see odd diffs, rebase main into this branch.

New type declarations

packages/cli-kit/dist/public/node/api/signups.d.ts
import { GraphQLVariables } from './graphql.js';
/**
 * Executes a GraphQL query against the Signups API.
 * Uses the Identity bearer token directly (no application token exchange).
 *
 * @param query - GraphQL query to execute.
 * @param token - Identity access token.
 * @param variables - GraphQL variables to pass to the query.
 * @returns The response of the query of generic type <T>.
 */
export declare function signupsRequest<T>(query: string, token: string, variables?: GraphQLVariables): Promise<T>;

Existing type declarations

packages/cli-kit/dist/private/node/session.d.ts
@@ -41,6 +41,15 @@ interface BusinessPlatformAPIOAuthOptions {
     /** List of scopes to request permissions for. */
     scopes: BusinessPlatformScope[];
 }
+/**
+ * A scope supported by the Signups API.
+ * The Signups API uses the Identity bearer token directly (no application token exchange).
+ */
+export type SignupsScope = 'shop-create';
+interface SignupsAPIOAuthOptions {
+    /** List of scopes to request permissions for. */
+    scopes: SignupsScope[];
+}
 /**
  * It represents the authentication requirements and
  * is the input necessary to trigger the authentication
@@ -52,6 +61,7 @@ export interface OAuthApplications {
     partnersApi?: PartnersAPIOAuthOptions;
     businessPlatformApi?: BusinessPlatformAPIOAuthOptions;
     appManagementApi?: AppManagementAPIOauthOptions;
+    signupsApi?: SignupsAPIOAuthOptions;
 }
 export interface OAuthSession {
     admin?: AdminSession;
@@ -59,6 +69,7 @@ export interface OAuthSession {
     storefront?: string;
     businessPlatform?: string;
     appManagement?: string;
+    identity?: string;
     userId: string;
 }
 type AuthMethod = 'partners_token' | 'device_auth' | 'theme_access_token' | 'custom_app_token' | 'none';
packages/cli-kit/dist/public/node/session.d.ts
@@ -1,4 +1,4 @@
-import { AdminAPIScope, AppManagementAPIScope, BusinessPlatformScope, EnsureAuthenticatedAdditionalOptions, PartnersAPIScope, StorefrontRendererScope } from '../../private/node/session.js';
+import { AdminAPIScope, AppManagementAPIScope, BusinessPlatformScope, EnsureAuthenticatedAdditionalOptions, PartnersAPIScope, SignupsScope, StorefrontRendererScope } from '../../private/node/session.js';
 /**
  * Session Object to access the Admin API, includes the token and the store FQDN.
  */
@@ -116,6 +116,19 @@ export declare function ensureAuthenticatedThemes(store: string, password: strin
  * @returns The access token for the Business Platform API.
  */
 export declare function ensureAuthenticatedBusinessPlatform(scopes?: BusinessPlatformScope[]): Promise<string>;
+/**
+ * Ensure that we have a valid session to access the Signups API.
+ * The Signups API uses the Identity bearer token directly (no application token exchange).
+ *
+ * @param scopes - Optional array of extra scopes to authenticate with.
+ * @param env - Optional environment variables to use.
+ * @param options - Optional extra options to use.
+ * @returns The Identity access token and user ID.
+ */
+export declare function ensureAuthenticatedSignups(scopes?: SignupsScope[], env?: NodeJS.ProcessEnv, options?: EnsureAuthenticatedAdditionalOptions): Promise<{
+    token: string;
+    userId: string;
+}>;
 /**
  * Logout from Shopify.
  *
packages/cli-kit/dist/public/node/context/fqdn.d.ts
@@ -37,6 +37,12 @@ export declare function developerDashboardFqdn(): Promise<string>;
  * @returns Fully-qualified domain of the partners service we should interact with.
  */
 export declare function businessPlatformFqdn(): Promise<string>;
+/**
+ * It returns the Signups API service we should interact with.
+ *
+ * @returns Fully-qualified domain of the Signups service we should interact with.
+ */
+export declare function signupsFqdn(): Promise<string>;
 /**
  * It returns the Identity service we should interact with.
  *

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants