Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ export const CONFIG_EXTENSION_IDS: string[] = [
WebhookSubscriptionSpecIdentifier,
WebhooksSpecIdentifier,
EventsSpecIdentifier,
'admin',
]

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import {buildFunctionExtension} from '../extension.js'
import type {LifecycleStep, BuildContext} from '../client-steps.js'

/**
* Executes a build_function build step.
*
* Compiles the function extension (JavaScript or other language) to WASM,
* applying wasm-opt and trampoline as configured.
*/
export async function executeBuildFunctionStep(_step: LifecycleStep, context: BuildContext): Promise<void> {
return buildFunctionExtension(context.extension, context.options)
}
14 changes: 14 additions & 0 deletions packages/app/src/cli/services/build/steps/build-theme-step.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {runThemeCheck} from '../theme-check.js'
import type {LifecycleStep, BuildContext} from '../client-steps.js'

/**
* Executes a build_theme build step.
*
* Runs theme check on the extension directory and writes any offenses to stdout.
*/
export async function executeBuildThemeStep(_step: LifecycleStep, context: BuildContext): Promise<void> {
const {extension, options} = context
options.stdout.write(`Running theme check on your Theme app extension...`)
const offenses = await runThemeCheck(extension.directory)
if (offenses) options.stdout.write(offenses)
}
30 changes: 30 additions & 0 deletions packages/app/src/cli/services/build/steps/bundle-theme-step.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import {themeExtensionFiles} from '../../../utilities/extensions/theme.js'
import {copyFile} from '@shopify/cli-kit/node/fs'
import {relativePath, joinPath} from '@shopify/cli-kit/node/path'
import type {LifecycleStep, BuildContext} from '../client-steps.js'

/**
* Executes a bundle_theme build step.
*
* Copies theme extension files to the output directory, preserving relative paths.
* Respects the extension's .shopifyignore file and the standard ignore patterns.
*/
export async function executeBundleThemeStep(
_step: LifecycleStep,
context: BuildContext,
): Promise<{filesCopied: number}> {
const {extension, options} = context
options.stdout.write(`Bundling theme extension ${extension.localIdentifier}...`)
const files = await themeExtensionFiles(extension)

await Promise.all(
files.map(async (filepath) => {
const relativePathName = relativePath(extension.directory, filepath)
const outputFile = joinPath(extension.outputPath, relativePathName)
if (filepath === outputFile) return
await copyFile(filepath, outputFile)
}),
)

return {filesCopied: files.length}
}
11 changes: 11 additions & 0 deletions packages/app/src/cli/services/build/steps/bundle-ui-step.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {buildUIExtension} from '../extension.js'
import type {LifecycleStep, BuildContext} from '../client-steps.js'

/**
* Executes a bundle_ui build step.
*
* Bundles the UI extension using esbuild, writing output to extension.outputPath.
*/
export async function executeBundleUIStep(_step: LifecycleStep, context: BuildContext): Promise<void> {
return buildUIExtension(context.extension, context.options)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import type {LifecycleStep, BuildContext} from '../client-steps.js'

/**
* Executes a copy_static_assets build step.
*
* Copies static assets defined in the extension's build_manifest to the output directory.
* This is a no-op for extensions that do not define static assets.
*/
export async function executeCopyStaticAssetsStep(_step: LifecycleStep, context: BuildContext): Promise<void> {
Copy link
Contributor

Choose a reason for hiding this comment

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

are we ever using _step? why is it included?

return context.extension.copyStaticAssets()
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import {touchFile, writeFile} from '@shopify/cli-kit/node/fs'
import type {LifecycleStep, BuildContext} from '../client-steps.js'

/**
* Executes a create_tax_stub build step.
*
* Creates a minimal JavaScript stub file at the extension's output path,
* satisfying the tax calculation extension bundle format.
*/
export async function executeCreateTaxStubStep(_step: LifecycleStep, context: BuildContext): Promise<void> {
const {extension} = context
await touchFile(extension.outputPath)
await writeFile(extension.outputPath, '(()=>{})();')

Choose a reason for hiding this comment

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

Tax stub step can overwrite a directory with a JS file

The step writes the stub to extension.outputPath directly. If outputPath is configured as a directory (which the include_assets step supports when “no extension”), this will attempt to write a file over a directory path and fail, or clobber expected directory structure.

Evidence:

await touchFile(extension.outputPath)
await writeFile(extension.outputPath, '(()=>{})();')

}
Loading
Loading