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
9 changes: 9 additions & 0 deletions packages/catalyst/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,14 +22,20 @@
"node": "^20.0.0 || ^22.0.0 || ^24.0.0"
},
"dependencies": {
"@inquirer/prompts": "^7.5.3",
"@segment/analytics-node": "^2.2.1",
"adm-zip": "^0.5.16",
"commander": "^14.0.0",
"conf": "^13.1.0",
"consola": "^3.4.2",
"cross-spawn": "^7.0.6",
"dotenv": "^16.5.0",
"execa": "^9.6.0",
"fs-extra": "^11.3.0",
"lodash.kebabcase": "^4.1.1",
"nypm": "^0.5.4",
"open": "^10.1.0",
"std-env": "^3.9.0",
"yocto-spinner": "^1.0.0",
"zod": "^4.0.5"
},
Expand All @@ -38,6 +44,9 @@
"@bigcommerce/eslint-config-catalyst": "workspace:^",
"@commander-js/extra-typings": "^14.0.0",
"@types/adm-zip": "^0.5.7",
"@types/cross-spawn": "^6.0.6",
"@types/fs-extra": "^11.0.4",
"@types/lodash.kebabcase": "^4.1.9",
"@types/node": "^22.15.30",
"@vitest/coverage-v8": "^3.2.4",
"@vitest/ui": "^3.2.4",
Expand Down
50 changes: 49 additions & 1 deletion packages/catalyst/src/cli/commands/build.spec.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,63 @@
import { Command } from 'commander';
import { expect, test, vi } from 'vitest';
import { execa } from 'execa';
import { afterEach, beforeAll, beforeEach, expect, test, vi } from 'vitest';

import { consola } from '../lib/logger';
import { getProjectState } from '../lib/project-state';
import { program } from '../program';

import { build } from './build';

vi.mock('execa', () => ({
execa: vi.fn(() => Promise.resolve({})),
__esModule: true,
}));

vi.mock('../lib/project-state', () => ({
getProjectState: vi.fn(),
}));

const untransformedState = {
projectUuid: undefined,
hasMiddleware: false,
hasProxy: true,
hasOpenNextDep: false,
isLinked: false,
isTransformed: false,
isFullySetUp: false,
};

// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
vi.spyOn(process, 'exit').mockImplementation(() => null as never);

beforeAll(() => {
consola.wrapAll();
});

beforeEach(() => {
consola.mockTypes(() => vi.fn());
});

afterEach(() => {
vi.clearAllMocks();
});

test('properly configured Command instance', () => {
expect(build).toBeInstanceOf(Command);
expect(build.name()).toBe('build');
expect(build.options).toEqual(
expect.arrayContaining([expect.objectContaining({ long: '--project-uuid' })]),
);
});

test('falls through to `next build` when project is not transformed', async () => {
vi.mocked(getProjectState).mockReturnValue(untransformedState);

await program.parseAsync(['node', 'catalyst', 'build']);

expect(execa).toHaveBeenCalledWith(
'pnpm',
['exec', 'next', 'build'],
expect.objectContaining({ stdio: 'inherit', cwd: process.cwd() }),
);
});
18 changes: 18 additions & 0 deletions packages/catalyst/src/cli/commands/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { join } from 'node:path';
import { getModuleCliPath } from '../lib/get-module-cli-path';
import { consola } from '../lib/logger';
import { getProjectConfig } from '../lib/project-config';
import { getProjectState } from '../lib/project-state';
import { getWranglerConfig } from '../lib/wrangler-config';

const WRANGLER_VERSION = '4.24.3';
Expand Down Expand Up @@ -96,6 +97,23 @@ Examples:
).env('CATALYST_PROJECT_UUID'),
)
.action(async (options) => {
// Project must be transformed (middleware swapped in, OpenNext dep installed)
// before the OpenNext build pipeline can run. If it isn't, fall through to
// `next build` so this command works for self-hosted Catalyst projects too.
const state = getProjectState();

if (!state.isTransformed) {
consola.info('Project is not set up for Commerce Hosting — running `next build`.');
consola.info('To deploy to Commerce Hosting, run `catalyst deploy`.');

await execa('pnpm', ['exec', 'next', 'build'], {
stdio: 'inherit',
cwd: process.cwd(),
});

return;
}

const config = getProjectConfig();
const projectUuid = options.projectUuid ?? config.get('projectUuid');

Expand Down
Loading
Loading