Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add and implement codegen in hello-world #1039

Closed
wants to merge 10 commits into from
Closed
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
5 changes: 5 additions & 0 deletions .changeset/smooth-colts-reflect.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@shopify/cli-hydrogen': patch
---

Add `--codegen-unstable` flag to `build` command.
2 changes: 1 addition & 1 deletion packages/cli/oclif.manifest.json

Large diffs are not rendered by default.

20 changes: 19 additions & 1 deletion packages/cli/src/commands/hydrogen/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import {deprecated, commonFlags, flagsToCamelObject} from '../../lib/flags.js';
import {checkLockfileStatus} from '../../lib/check-lockfile.js';
import {findMissingRoutes} from '../../lib/missing-routes.js';
import {warnOnce} from '../../lib/log.js';
import {codegen} from '../../lib/codegen.js';

const LOG_WORKER_BUILT = '📦 Worker built';

Expand All @@ -41,6 +42,14 @@ export default class Build extends Command {
description: 'Disable warning about missing standard routes.',
env: 'SHOPIFY_HYDROGEN_FLAG_DISABLE_ROUTE_WARNING',
}),
['codegen-unstable']: Flags.boolean({
description:
'Generate types for the Storefront API queries found in your project.',
required: false,
default: false,
}),
['codegen-config-path']: commonFlags.codegenConfigPath,

base: deprecated('--base')(),
entry: deprecated('--entry')(),
target: deprecated('--target')(),
Expand All @@ -50,16 +59,24 @@ export default class Build extends Command {
const {flags} = await this.parse(Build);
const directory = flags.path ? resolvePath(flags.path) : process.cwd();

await runBuild({...flagsToCamelObject(flags), path: directory});
await runBuild({
...flagsToCamelObject(flags),
useCodegen: flags['codegen-unstable'],
path: directory,
});
}
}

export async function runBuild({
path: appPath,
useCodegen = false,
codegenConfigPath,
sourcemap = false,
disableRouteWarning = false,
}: {
path?: string;
useCodegen?: boolean;
codegenConfigPath?: string;
sourcemap?: boolean;
disableRouteWarning?: boolean;
}) {
Expand Down Expand Up @@ -99,6 +116,7 @@ export async function runBuild({
logThrown(thrown);
process.exit(1);
}),
useCodegen && codegen({...remixConfig, configFilePath: codegenConfigPath}),
]);

if (process.env.NODE_ENV !== 'development') {
Expand Down
44 changes: 14 additions & 30 deletions packages/cli/src/commands/hydrogen/codegen-unstable.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import path from 'path';
import Command from '@shopify/cli-kit/node/base-command';
import {AbortError} from '@shopify/cli-kit/node/error';
import {renderSuccess} from '@shopify/cli-kit/node/ui';
import {Flags} from '@oclif/core';
import {getProjectPaths, getRemixConfig} from '../../lib/config.js';
import {commonFlags, flagsToCamelObject} from '../../lib/flags.js';
import {
generateTypes,
normalizeCodegenError,
patchGqlPluck,
} from '../../lib/codegen.js';
import {codegen} from '../../lib/codegen.js';

export default class Codegen extends Command {
static description =
Expand Down Expand Up @@ -45,7 +40,7 @@ export default class Codegen extends Command {
}
}

async function runCodegen({
export async function runCodegen({
path: appPath,
codegenConfigPath,
forceSfapiVersion,
Expand All @@ -59,30 +54,19 @@ async function runCodegen({
const {root} = getProjectPaths(appPath);
const remixConfig = await getRemixConfig(root);

await patchGqlPluck();
console.log(''); // New line

try {
const generatedFiles = await generateTypes({
...remixConfig,
configFilePath: codegenConfigPath,
forceSfapiVersion,
watch,
});

if (!watch) {
console.log('');
renderSuccess({
headline: 'Generated types for GraphQL:',
body: generatedFiles.map((file) => `- ${file}`).join('\n'),
});
}
} catch (error) {
const {message, details} = normalizeCodegenError(
(error as Error).message,
remixConfig.rootDirectory,
);
const generatedFiles = await codegen({
...remixConfig,
configFilePath: codegenConfigPath,
forceSfapiVersion,
watch,
});

console.log('');
throw new AbortError(message, details);
if (!watch) {
renderSuccess({
headline: 'Generated types for GraphQL:',
body: generatedFiles.map((file) => `- ${file}`).join('\n'),
});
}
}
15 changes: 5 additions & 10 deletions packages/cli/src/commands/hydrogen/dev.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,7 @@ export default class Dev extends Command {
required: false,
default: false,
}),
['codegen-config-path']: Flags.string({
description:
'Specify a path to a codegen configuration file. Defaults to `<root>/codegen.ts` if it exists.',
required: false,
dependsOn: ['codegen-unstable'],
}),
['codegen-config-path']: commonFlags.codegenConfigPath,
sourcemap: commonFlags.sourcemap,
'disable-virtual-routes': Flags.boolean({
description:
Expand All @@ -65,7 +60,7 @@ export default class Dev extends Command {

await runDev({
...flagsToCamelObject(flags),
codegen: flags['codegen-unstable'],
useCodegen: flags['codegen-unstable'],
path: directory,
});
}
Expand All @@ -74,7 +69,7 @@ export default class Dev extends Command {
async function runDev({
port,
path: appPath,
codegen = false,
useCodegen = false,
codegenConfigPath,
disableVirtualRoutes,
shop,
Expand All @@ -84,7 +79,7 @@ async function runDev({
}: {
port?: number;
path?: string;
codegen?: boolean;
useCodegen?: boolean;
codegenConfigPath?: string;
disableVirtualRoutes?: boolean;
shop?: string;
Expand Down Expand Up @@ -167,7 +162,7 @@ async function runDev({

const remixConfig = await reloadConfig();

if (codegen) {
if (useCodegen) {
spawnCodegenProcess({...remixConfig, configFilePath: codegenConfigPath});
}

Expand Down
46 changes: 27 additions & 19 deletions packages/cli/src/lib/codegen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,31 +11,25 @@ import {
} from '@shopify/hydrogen-codegen';
import {format, resolveFormatConfig} from './transpile-ts.js';
import {renderFatalError, renderWarning} from '@shopify/cli-kit/node/ui';
import {joinPath, relativePath} from '@shopify/cli-kit/node/path';
import {joinPath} from '@shopify/cli-kit/node/path';
import {AbortError} from '@shopify/cli-kit/node/error';
import {spawn} from 'node:child_process';
import {fileURLToPath} from 'node:url';

export {patchGqlPluck} from '@shopify/hydrogen-codegen';

const nodePath = process.argv[1];
const modulePath = fileURLToPath(import.meta.url);
const isStandaloneProcess = nodePath === modulePath;

if (isStandaloneProcess) {
patchGqlPluck().then(() =>
generateTypes({
rootDirectory: process.argv[2]!,
appDirectory: process.argv[3]!,
configFilePath: process.argv[4],
watch: true,
}),
);
codegen({
rootDirectory: process.argv[2]!,
appDirectory: process.argv[3]!,
configFilePath: process.argv[4],
watch: true,
});
}

export function normalizeCodegenError(
errorMessage: string,
rootDirectory?: string,
) {
function normalizeCodegenError(errorMessage: string, rootDirectory?: string) {
const [first = '', ...rest] = errorMessage
.replaceAll('[FAILED]', '')
.replace(/\s{2,}/g, '\n')
Expand Down Expand Up @@ -115,7 +109,22 @@ type CodegenOptions = ProjectDirs & {
forceSfapiVersion?: string;
};

export async function generateTypes({
export async function codegen(options: CodegenOptions) {
await patchGqlPluck();

try {
return await generateTypes(options);
} catch (error) {
const {message, details} = normalizeCodegenError(
(error as Error).message,
options.rootDirectory,
);

throw new AbortError(message, details);
}
}

async function generateTypes({
watch,
configFilePath,
forceSfapiVersion,
Expand Down Expand Up @@ -152,7 +161,6 @@ function generateDefaultConfig(
forceSfapiVersion?: string,
): LoadCodegenConfigResult {
const tsDefaultGlob = '*!(*.d).{ts,tsx}'; // No d.ts files
const appDirRelative = relativePath(rootDirectory, appDirectory);

return {
filepath: 'virtual:codegen',
Expand All @@ -164,8 +172,8 @@ function generateDefaultConfig(
preset,
schema,
documents: [
tsDefaultGlob, // E.g. ./server.ts
joinPath(appDirRelative, '**', tsDefaultGlob), // E.g. app/routes/_index.tsx
joinPath(rootDirectory, tsDefaultGlob), // E.g. ./server.ts
joinPath(appDirectory, '**', tsDefaultGlob), // E.g. app/routes/_index.tsx
],

...(!!forceSfapiVersion && {
Expand Down
6 changes: 6 additions & 0 deletions packages/cli/src/lib/flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ export const commonFlags = {
default: true,
allowNo: true,
}),
codegenConfigPath: Flags.string({
description:
'Specify a path to a codegen configuration file. Defaults to `<root>/codegen.ts` if it exists.',
required: false,
dependsOn: ['codegen-unstable'],
}),
};

export function flagsToCamelObject(obj: Record<string, any>) {
Expand Down
9 changes: 5 additions & 4 deletions packages/cli/src/lib/transpile-ts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,11 +195,12 @@ export async function transpileProject(projectDir: string) {
}
}

const codegenFlag = /\s*--codegen(-unstable)?/;
if (pkgJson.scripts?.dev) {
pkgJson.scripts.dev = pkgJson.scripts.dev.replace(
/\s*--codegen(-unstable)?/,
'',
);
pkgJson.scripts.dev = pkgJson.scripts.dev.replace(codegenFlag, '');
}
if (pkgJson.scripts?.build) {
pkgJson.scripts.build = pkgJson.scripts.build.replace(codegenFlag, '');
}

await fs.writeFile(
Expand Down
2 changes: 1 addition & 1 deletion packages/create-hydrogen/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
"typecheck": "tsc --noEmit"
},
"dependencies": {
"@shopify/cli-hydrogen": "^5.0.2"
"@shopify/cli-hydrogen": "^5.0.1"
},
"bin": "dist/create-app.js",
"files": [
Expand Down
4 changes: 4 additions & 0 deletions templates/demo-store/app/lib/session.server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ export class HydrogenSession {
return new this(storage, session);
}

has(key: string) {
return this.session.has(key);
}

get(key: string) {
return this.session.get(key);
}
Expand Down
1 change: 1 addition & 0 deletions templates/hello-world/.gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ node_modules
/.mf
.env
.shopify
storefrontapi.generated.d.ts
20 changes: 9 additions & 11 deletions templates/hello-world/app/root.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import {type LinksFunction, type LoaderArgs} from '@shopify/remix-oxygen';
import {json, type LoaderArgs} from '@shopify/remix-oxygen';
import {
Links,
Meta,
Expand All @@ -7,11 +7,10 @@ import {
ScrollRestoration,
useLoaderData,
} from '@remix-run/react';
import type {Shop} from '@shopify/hydrogen/storefront-api-types';
import styles from './styles/app.css';
import favicon from '../public/favicon.svg';

export const links: LinksFunction = () => {
export function links() {
return [
{rel: 'stylesheet', href: styles},
{
Expand All @@ -24,17 +23,16 @@ export const links: LinksFunction = () => {
},
{rel: 'icon', type: 'image/svg+xml', href: favicon},
];
};
}

export async function loader({context}: LoaderArgs) {
const layout = await context.storefront.query<{shop: Shop}>(LAYOUT_QUERY);
return {layout};
const layout = await context.storefront.query(LAYOUT_QUERY);
return json({layout});
}

export default function App() {
const data = useLoaderData<typeof loader>();

const {name} = data.layout.shop;
const {layout} = useLoaderData<typeof loader>();
const {name, description} = layout.shop;

return (
<html lang="en">
Expand All @@ -46,7 +44,7 @@ export default function App() {
</head>
<body>
<h1>Hello, {name}</h1>
<p>This is a custom storefront powered by Hydrogen</p>
{description && <p>{description}</p>}
<Outlet />
<ScrollRestoration />
<Scripts />
Expand All @@ -62,4 +60,4 @@ const LAYOUT_QUERY = `#graphql
description
}
}
`;
` as const;
4 changes: 2 additions & 2 deletions templates/hello-world/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
"sideEffects": false,
"version": "0.0.0",
"scripts": {
"build": "shopify hydrogen build",
"dev": "shopify hydrogen dev",
"build": "shopify hydrogen build --codegen-unstable",
"dev": "shopify hydrogen dev --codegen-unstable",
"preview": "npm run build && shopify hydrogen preview",
"lint": "eslint --no-error-on-unmatched-pattern --ext .js,.ts,.jsx,.tsx .",
"typecheck": "tsc --noEmit"
Expand Down
4 changes: 4 additions & 0 deletions templates/hello-world/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,10 @@ export class HydrogenSession {
return new this(storage, session);
}

has(key: string) {
return this.session.has(key);
}

get(key: string) {
return this.session.get(key);
}
Expand Down
Loading