Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 0 additions & 4 deletions packages/cli/json-output-command-exceptions.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,6 @@
const commandExceptions = [
// Existing finite commands awaiting migration. Remove entries as they adopt typed JSON output.
// Do not add new finite commands to this section.
'packages/cli/src/commands/hydrogen/setup.ts',
'packages/cli/src/commands/hydrogen/setup/css.ts',
'packages/cli/src/commands/hydrogen/setup/markets.ts',
'packages/cli/src/commands/hydrogen/setup/vite.ts',
'packages/cli/src/commands/hydrogen/shortcut.ts',
'packages/cli/src/commands/hydrogen/upgrade.ts',

Expand Down
46 changes: 42 additions & 4 deletions packages/cli/oclif.manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -1733,7 +1733,7 @@
"hydrogen:setup": {
"aliases": [],
"args": {},
"description": "Scaffold routes and core functionality.",
"description": "Scaffold routes and core functionality.\n\nUse `--json-schema` to print the result, error, and event schemas.\n\nOutput from `--json` conforms to the `HydrogenSetupResult` schema.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"directory\": {\n \"type\": \"string\"\n },\n \"name\": {\n \"type\": \"string\"\n },\n \"location\": {\n \"type\": \"string\"\n },\n \"i18n\": {\n \"type\": \"string\",\n \"enum\": [\n \"subfolders\",\n \"domains\",\n \"subdomains\"\n ]\n },\n \"routes\": {\n \"type\": \"object\",\n \"additionalProperties\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n }\n },\n \"shortcut\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"directory\",\n \"name\",\n \"location\",\n \"shortcut\"\n ],\n \"additionalProperties\": false,\n \"title\": \"HydrogenSetupResult\",\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n}\n```",
"flags": {
"json-schema": {
"description": "Print the command's JSON schemas.",
Expand All @@ -1742,6 +1742,15 @@
"allowNo": false,
"type": "boolean"
},
"json": {
"char": "j",
"description": "Output the result as JSON. Automatically disables color output.",
"env": "SHOPIFY_FLAG_JSON",
"hidden": false,
"name": "json",
"allowNo": false,
"type": "boolean"
},
"path": {
"description": "The path to the directory of the Hydrogen storefront. Defaults to the current directory where the command is run.",
"env": "SHOPIFY_HYDROGEN_FLAG_PATH",
Expand Down Expand Up @@ -1789,6 +1798,7 @@
"pluginType": "core",
"strict": true,
"enableJsonFlag": false,
"descriptionWithMarkdown": "Scaffold routes and core functionality.",
"isESM": true,
"relativePath": [
"dist",
Expand All @@ -1811,7 +1821,7 @@
]
}
},
"description": "Setup CSS strategies for your project.",
"description": "Adds support for certain CSS strategies to your project.\n\nUse `--json-schema` to print the result, error, and event schemas.\n\nOutput from `--json` conforms to the `HydrogenSetupCssResult` schema.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"status\": {\n \"type\": \"string\",\n \"enum\": [\n \"configured\",\n \"built-in\",\n \"cancelled\"\n ]\n },\n \"directory\": {\n \"type\": \"string\"\n },\n \"strategy\": {\n \"type\": \"string\",\n \"enum\": [\n \"tailwind\",\n \"vanilla-extract\",\n \"css-modules\",\n \"postcss\"\n ]\n },\n \"files\": {\n \"type\": \"array\",\n \"items\": {\n \"type\": \"string\"\n }\n },\n \"dependenciesInstalled\": {\n \"type\": \"boolean\"\n },\n \"needsNpmReinstall\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"status\",\n \"directory\",\n \"strategy\",\n \"files\",\n \"dependenciesInstalled\",\n \"needsNpmReinstall\"\n ],\n \"additionalProperties\": false,\n \"title\": \"HydrogenSetupCssResult\",\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n}\n```",
"flags": {
"json-schema": {
"description": "Print the command's JSON schemas.",
Expand All @@ -1820,6 +1830,15 @@
"allowNo": false,
"type": "boolean"
},
"json": {
"char": "j",
"description": "Output the result as JSON. Automatically disables color output.",
"env": "SHOPIFY_FLAG_JSON",
"hidden": false,
"name": "json",
"allowNo": false,
"type": "boolean"
},
"path": {
"description": "The path to the directory of the Hydrogen storefront. Defaults to the current directory where the command is run.",
"env": "SHOPIFY_HYDROGEN_FLAG_PATH",
Expand Down Expand Up @@ -1875,7 +1894,7 @@
]
}
},
"description": "Setup support for multiple markets in your project.",
"description": "Adds support for multiple \"markets\" (https://shopify.dev/docs/custom-storefronts/hydrogen/markets) to your project by using the URL structure.\n\nUse `--json-schema` to print the result, error, and event schemas.\n\nOutput from `--json` conforms to the `HydrogenSetupMarketsResult` schema.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"directory\": {\n \"type\": \"string\"\n },\n \"strategy\": {\n \"type\": \"string\",\n \"enum\": [\n \"subfolders\",\n \"domains\",\n \"subdomains\"\n ]\n },\n \"serverEntryPoint\": {\n \"type\": \"string\"\n }\n },\n \"required\": [\n \"directory\",\n \"strategy\"\n ],\n \"additionalProperties\": false,\n \"title\": \"HydrogenSetupMarketsResult\",\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n}\n```",
"flags": {
"json-schema": {
"description": "Print the command's JSON schemas.",
Expand All @@ -1884,6 +1903,15 @@
"allowNo": false,
"type": "boolean"
},
"json": {
"char": "j",
"description": "Output the result as JSON. Automatically disables color output.",
"env": "SHOPIFY_FLAG_JSON",
"hidden": false,
"name": "json",
"allowNo": false,
"type": "boolean"
},
"path": {
"description": "The path to the directory of the Hydrogen storefront. Defaults to the current directory where the command is run.",
"env": "SHOPIFY_HYDROGEN_FLAG_PATH",
Expand Down Expand Up @@ -1914,7 +1942,7 @@
"hydrogen:setup:vite": {
"aliases": [],
"args": {},
"description": "EXPERIMENTAL: Upgrades the project to use Vite.",
"description": "EXPERIMENTAL: Upgrades the project to use Vite.\n\nUse `--json-schema` to print the result, error, and event schemas.\n\nOutput from `--json` conforms to the `HydrogenSetupViteResult` schema.\n\n```json\n{\n \"type\": \"object\",\n \"properties\": {\n \"directory\": {\n \"type\": \"string\"\n },\n \"viteConfig\": {\n \"type\": \"string\"\n },\n \"serverEntryPoint\": {\n \"type\": \"string\"\n },\n \"dependenciesInstalled\": {\n \"type\": \"boolean\",\n \"const\": true\n },\n \"needsMdxSetup\": {\n \"type\": \"boolean\"\n }\n },\n \"required\": [\n \"directory\",\n \"viteConfig\",\n \"serverEntryPoint\",\n \"dependenciesInstalled\",\n \"needsMdxSetup\"\n ],\n \"additionalProperties\": false,\n \"title\": \"HydrogenSetupViteResult\",\n \"$schema\": \"http://json-schema.org/draft-07/schema#\"\n}\n```",
"flags": {
"json-schema": {
"description": "Print the command's JSON schemas.",
Expand All @@ -1923,6 +1951,15 @@
"allowNo": false,
"type": "boolean"
},
"json": {
"char": "j",
"description": "Output the result as JSON. Automatically disables color output.",
"env": "SHOPIFY_FLAG_JSON",
"hidden": false,
"name": "json",
"allowNo": false,
"type": "boolean"
},
"path": {
"description": "The path to the directory of the Hydrogen storefront. Defaults to the current directory where the command is run.",
"env": "SHOPIFY_HYDROGEN_FLAG_PATH",
Expand All @@ -1940,6 +1977,7 @@
"pluginType": "core",
"strict": true,
"enableJsonFlag": false,
"descriptionWithMarkdown": "EXPERIMENTAL: Upgrades the project to use Vite.",
"isESM": true,
"relativePath": [
"dist",
Expand Down
78 changes: 59 additions & 19 deletions packages/cli/src/commands/hydrogen/setup.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import {writeJsonResult} from '../../lib/json-output.js';
import {jsonFlag} from '@shopify/cli-kit/node/cli';
import {setupJsonOutputSchema} from '../../lib/setups/types.js';
import Command from '@shopify/cli-kit/node/base-command';
import {AbortController} from '@shopify/cli-kit/node/abort';
import {renderTasks} from '../../lib/ui.js';
Expand All @@ -24,9 +27,16 @@ import {ALIAS_NAME, getCliCommand} from '../../lib/shell.js';
import {getTemplateAppFile} from '../../lib/build.js';

export default class Setup extends Command {
static description = 'Scaffold routes and core functionality.';
static get jsonOutputSchema(): typeof setupJsonOutputSchema {
return setupJsonOutputSchema;
}

static descriptionWithMarkdown = 'Scaffold routes and core functionality.';

static description = this.descriptionForHelp();

static flags = {
...jsonFlag,
...commonFlags.path,
...commonFlags.force,
...commonFlags.markets,
Expand All @@ -40,10 +50,13 @@ export default class Setup extends Command {
const {flags} = await this.parse(Setup);
const directory = flags.path ? resolvePath(flags.path) : process.cwd();

await runSetup({
...flagsToCamelObject(flags),
directory,
});
await runSetup(
{
...flagsToCamelObject(flags),
directory,
},
flags.json,
);
}
}

Expand All @@ -54,7 +67,7 @@ type RunSetupOptions = {
shortcut?: boolean;
};

export async function runSetup(options: RunSetupOptions) {
export async function executeSetup(options: RunSetupOptions) {
const controller = new AbortController();
const {rootDirectory, appDirectory} = await getRemixConfig(options.directory);

Expand Down Expand Up @@ -135,11 +148,25 @@ export async function runSetup(options: RunSetupOptions) {
options.shortcut,
);

if (!i18n && !createShortcut) return;
if (!i18n && !createShortcut) {
await backgroundWorkPromise;
return {
directory: rootDirectory,
name: location,
location,
i18n,
routes,
shortcut: false,
cliCommand,
showSummary: false,
};
}
let shortcut = false;

if (createShortcut) {
backgroundWorkPromise = backgroundWorkPromise.then(async () => {
if (await createShortcut()) {
shortcut = true;
cliCommand = ALIAS_NAME;
}
});
Expand All @@ -149,18 +176,31 @@ export async function runSetup(options: RunSetupOptions) {

await renderTasks(tasks);

await renderProjectReady(
{
location,
name: location,
directory: rootDirectory,
},
{
cliCommand,
return {
directory: rootDirectory,
name: location,
location,
i18n,
routes,
shortcut,
cliCommand,
showSummary: true,
};
}

export async function runSetup(options: RunSetupOptions, json?: boolean) {
const result = await executeSetup(options);
if (
!writeJsonResult(setupJsonOutputSchema, result, json) &&
result.showSummary
) {
await renderProjectReady(result, {
cliCommand: result.cliCommand,
depsInstalled: true,
packageManager: 'npm',
i18n,
routes,
},
);
i18n: result.i18n,
routes: result.routes,
});
}
return result;
}
87 changes: 63 additions & 24 deletions packages/cli/src/commands/hydrogen/setup/css.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import {writeJsonResult} from '../../../lib/json-output.js';
import {jsonFlag} from '@shopify/cli-kit/node/cli';
import {setupCssJsonOutputSchema} from '../../../lib/setups/types.js';
import {resolvePath} from '@shopify/cli-kit/node/path';
import {
commonFlags,
Expand All @@ -23,12 +26,17 @@ import {getViteConfig} from '../../../lib/vite-config.js';
import {AbortError} from '@shopify/cli-kit/node/error';

export default class SetupCSS extends Command {
static get jsonOutputSchema(): typeof setupCssJsonOutputSchema {
return setupCssJsonOutputSchema;
}

static descriptionWithMarkdown =
'Adds support for certain CSS strategies to your project.';

static description = 'Setup CSS strategies for your project.';
static description = this.descriptionForHelp();

static flags = {
...jsonFlag,
...commonFlags.path,
...commonFlags.force,
...overrideFlag(commonFlags.installDeps, {'install-deps': {default: true}}),
Expand All @@ -46,15 +54,18 @@ export default class SetupCSS extends Command {
const {flags, args} = await this.parse(SetupCSS);
const directory = flags.path ? resolvePath(flags.path) : process.cwd();

await runSetupCSS({
...flagsToCamelObject(flags),
strategy: args.strategy as CssStrategy,
directory,
});
await runSetupCSS(
{
...flagsToCamelObject(flags),
strategy: args.strategy as CssStrategy,
directory,
},
flags.json,
);
}
}

export async function runSetupCSS({
export async function executeSetupCSS({
strategy: flagStrategy,
directory,
force = false,
Expand All @@ -64,7 +75,7 @@ export async function runSetupCSS({
directory: string;
force?: boolean;
installDeps: boolean;
}) {
}): Promise<import('../../../lib/setups/types.js').SetupCssResult> {
const viteConfig = await getViteConfig(directory).catch(() => null);
if (!viteConfig) {
throw new AbortError(
Expand All @@ -76,17 +87,17 @@ export async function runSetupCSS({

const strategy = flagStrategy ? flagStrategy : await renderCssPrompt();

if (strategy === 'css-modules' || strategy === 'postcss') {
renderSuccess({
headline: `Vite works out of the box with ${CSS_STRATEGY_NAME_MAP[strategy]}.`,
body: `See the Vite documentation for more information:\n${CSS_STRATEGY_HELP_URL_MAP[strategy]}`,
});

return;
}

const result = {
directory,
strategy,
files: [] as string[],
dependenciesInstalled: false,
needsNpmReinstall: false,
};
if (strategy === 'css-modules' || strategy === 'postcss')
return {...result, status: 'built-in'};
const setupOutput = await setupCssStrategy(strategy, remixConfig, force);
if (!setupOutput) return;
if (!setupOutput) return {...result, status: 'cancelled'};

const {workPromise, generatedAssets, needsInstallDeps} = setupOutput;

Expand Down Expand Up @@ -123,6 +134,39 @@ export async function runSetupCSS({

await renderTasks(tasks);

return {
...result,
status: 'configured',
files: generatedAssets,
dependenciesInstalled: Boolean(installDeps && needsInstallDeps),
needsNpmReinstall: Boolean(
needsInstallDeps && isNpm && strategy === 'tailwind',
),
};
}

export async function runSetupCSS(
options: Parameters<typeof executeSetupCSS>[0],
json?: boolean,
) {
const result = await executeSetupCSS(options);
if (!writeJsonResult(setupCssJsonOutputSchema, result, json))
renderSetupCSS(result);
return result;
}

export function renderSetupCSS(
result: import('../../../lib/setups/types.js').SetupCssResult,
) {
const {strategy, files: generatedAssets} = result;
if (result.status === 'cancelled') return;
if (result.status === 'built-in') {
renderSuccess({
headline: `Vite works out of the box with ${CSS_STRATEGY_NAME_MAP[strategy]}.`,
body: `See the Vite documentation for more information:\n${CSS_STRATEGY_HELP_URL_MAP[strategy]}`,
});
return;
}
renderSuccess({
headline: `${CSS_STRATEGY_NAME_MAP[strategy]} setup complete.`,
body:
Expand All @@ -133,16 +177,11 @@ export async function runSetupCSS({
: '') +
`\nFor more information, visit ${CSS_STRATEGY_HELP_URL_MAP[strategy]}`,
});

// Due to a bug in NPM related to optional dependencies in Tailwind,
// we need to reinstall dependencies to fix node_modules:
// https://github.com/npm/cli/issues/4828
if (needsInstallDeps && isNpm && strategy === 'tailwind') {
if (result.needsNpmReinstall)
renderWarning({
body: [
'Due to a bug in NPM, you might need to reinstall dependencies again.\nRun',
{command: 'npm install'},
],
});
}
}
Loading
Loading