Skip to content

Add typed JSON output to Hydrogen build tooling - #4096

Draft
gonzaloriestra wants to merge 1 commit into
gonzalo/hydrogen-json-supportfrom
gonzalo/hydrogen-json-build
Draft

gonzaloriestra wants to merge 1 commit into
gonzalo/hydrogen-json-supportfrom
gonzalo/hydrogen-json-build

Conversation

@gonzaloriestra

@gonzaloriestra gonzaloriestra commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

WHY are these changes introduced?

Build, route checks and code generation currently expose terminal output that scripts cannot consume as a typed result.

WHAT is this pull request doing?

Add domain schemas and --json to build, check and codegen, with schema discovery and generated help. Keep build/codegen diagnostics separate from stdout, capture type-generation subprocess output, and reject --json --watch before execution.

Without --json, the existing terminal presentation remains. Example JSON result:

shopify hydrogen check routes --json
{"missingRoutes":[],"reservedRoutes":[]}

HOW to test your changes?

pnpm --filter @shopify/cli-hydrogen test src/commands/hydrogen/build-json.test.ts

Build and typecheck were checked at each layer. The full stack passed 498 tests (6 skipped), lint, and schema discovery for all 22 finite commands. Command-line smoke checks covered a successful unlink result, fatal project errors, watch-mode rejection and schema environment flags. Live authenticated Shopify operations have not been exercised.

Stack

Draft 2 of 9. Previous: #4095. Next: #4097. One changeset is included in #4103.

  1. Prepare Hydrogen commands for typed JSON output
  2. Add typed JSON output to Hydrogen build tooling
  3. Add typed JSON output to hydrogen customer-account-push
  4. Add typed JSON output to hydrogen deploy
  5. Add typed JSON output to Hydrogen environment commands
  6. Add typed JSON output to Hydrogen route generation
  7. Add typed JSON output to Hydrogen project and account commands
  8. Add typed JSON output to Hydrogen setup commands
  9. Add typed JSON output to Hydrogen maintenance commands

@shopify

shopify Bot commented Sep 28, 2026 •

Copy link
Copy Markdown
Contributor

Oxygen deployed a preview of your gonzalo/hydrogen-json-build branch. Details:

Storefront Status Preview link Deployment details Last update (UTC)
Skeleton (skeleton.hydrogen.shop) ✅ Successful (Logs) Preview deployment Inspect deployment September 29, 2026 2:55 PM

Learn more about Hydrogen's GitHub integration.

@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/hydrogen-json-build branch from 7052847 to 43c52f2 Compare September 29, 2026 12:25
@gonzaloriestra
gonzaloriestra force-pushed the gonzalo/hydrogen-json-build branch from 43c52f2 to d964345 Compare September 29, 2026 14:53

@fredericoo fredericoo left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

nice and tidy - pulling checkRoutes out as a pure function returning the domain result is a good shape, and the human output looks unchanged. A few small comments, mainly Vite's TTY progress output possibly getting into stdout in JSON mode, and codegen detecting --json differently from build/check.

customLogger.error = (msg) => collectLog('error', msg);
}

if (isJsonOutput()) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

non-blocking: overriding the logger methods covers the logs that go through customLogger, but IIRC Vite's build reporter also writes progress straight to process.stdout (transforming (N) ..., rendering chunks (N)..., computing gzip size (N)... plus the matching clearLine escapes) when process.stdout.isTTY && !process.env.CI. It checks config.logLevel, not the custom logger, so that path is untouched here.

build --json | jq is fine because stdout isn't a TTY there, but anything that runs the command under a PTY (some agent harnesses, script, etc.) might end up with progress fragments before the JSON document, and parsing would fail.

Setting logLevel: 'warn' in commonConfig when isJsonOutput() should switch the reporter off, if I'm not mistaken. We'd lose the N modules transformed / chunk table diagnostics, which seems fine for JSON consumers. What do you reckon?


if (!watch) {
const result = {generatedFiles};
if (!watch && !writeJsonResult(codegenJsonOutputSchema, result)) {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

non-blocking: build and check both pass flags.json to writeJsonResult, but runCodegen never gets it and falls back to the ambient isJsonOutput(). They should agree in practice, but let's pass it through the same way so all three commands in this PR decide JSON mode the same way, yeah? It also means the Codegen tests exercise the flag rather than only captureJsonOutput's env/argv setup.

});

it('encodes build output paths through the real writer', async () => {
const result = {

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

non-blocking: this test only covers writeJsonResult and the schema. It doesn't run Build or runBuild, so if the writeJsonResult call in Build.run or the Vite logger rerouting to diagnostics broke, it would still pass. The Vite build is a lot to mock, so not fussed about full coverage, but even a test that stubs runBuild and checks that Build.run writes result.result to stdout with --json would cover the wiring. process.exit would need stubbing too.

This branch has not been deployed

No deployments
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