Skip to content

Commit

Permalink
Merge pull request #3276 from Shopify/jmeng/theme_push_migration
Browse files Browse the repository at this point in the history
Jmeng/theme push migration
  • Loading branch information
jamesmengo committed Mar 22, 2024
2 parents 17f4bb8 + b356254 commit f8ed8f9
Show file tree
Hide file tree
Showing 17 changed files with 1,483 additions and 108 deletions.
51 changes: 20 additions & 31 deletions packages/cli-kit/src/public/node/themes/api.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
AssetParams,
deleteThemeAsset,
} from './api.js'
import {RemoteBulkUploadResponse} from './factories.js'
import {test, vi, expect, describe} from 'vitest'
import {restRequest} from '@shopify/cli-kit/node/api/admin'
import {AbortError} from '@shopify/cli-kit/node/error'
Expand Down Expand Up @@ -322,40 +323,25 @@ describe('bulkUploadThemeAssets', async () => {
const id = 123
const assets: AssetParams[] = [
{key: 'snippets/product-variant-picker.liquid', value: 'content'},
{key: 'templates/404.json', value: 'content'},
{key: 'templates/404.json', value: 'to_be_replaced_with_hash'},
]

const mockResults = [
const mockResults: RemoteBulkUploadResponse[] = [
{
code: 200,
body: {
asset: {
key: 'assets/test.liquid',
public_url: 'https://cdn.shopify.com/dummy_url',
created_at: '2024-01-24T16:26:13-08:00',
updated_at: '2024-01-24T16:26:13-08:00',
content_type: 'application/x-liquid',
size: 20,
checksum: '3f26c8569292ce6f1cc991c5fa7d3fcb',
theme_id: 139503010036,
warnings: [],
attachment: '',
value: '',
},
},
},
{
code: 200,
code: 400,
body: {
asset: {
key: 'config/settings_data.json',
public_url: null,
created_at: '2024-01-24T16:18:30-08:00',
updated_at: '2024-01-24T16:26:14-08:00',
content_type: 'application/json',
size: 19,
checksum: '336e955222ddd34b61d0f11940208640',
theme_id: 139503010036,
warnings: [],
},
errors: {asset: ['expected Hash to be a String']},
},
},
]
Expand All @@ -377,27 +363,30 @@ describe('bulkUploadThemeAssets', async () => {
{
assets: [
{key: 'snippets/product-variant-picker.liquid', value: 'content'},
{key: 'templates/404.json', value: 'content'},
{key: 'templates/404.json', value: 'to_be_replaced_with_hash'},
],
},
{},
)
expect(bulkUploadresults).toHaveLength(2)
expect(bulkUploadresults[0]).toEqual({
key: 'assets/test.liquid',
key: 'snippets/product-variant-picker.liquid',
success: true,
errors: [],
errors: {},
operation: 'UPLOAD',
asset: {
attachment: '',
key: 'assets/test.liquid',
public_url: 'https://cdn.shopify.com/dummy_url',
created_at: '2024-01-24T16:26:13-08:00',
updated_at: '2024-01-24T16:26:13-08:00',
content_type: 'application/x-liquid',
size: 20,
checksum: '3f26c8569292ce6f1cc991c5fa7d3fcb',
theme_id: 139503010036,
warnings: [],
value: '',
},
})
expect(bulkUploadresults[1]).toEqual({
key: 'templates/404.json',
operation: 'UPLOAD',
success: false,
errors: {asset: ['expected Hash to be a String']},
asset: undefined,
})
})
})
12 changes: 4 additions & 8 deletions packages/cli-kit/src/public/node/themes/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@ import {
buildTheme,
buildThemeAsset,
} from '@shopify/cli-kit/node/themes/factories'
import {BulkUploadResult, Checksum, Key, Theme, ThemeAsset} from '@shopify/cli-kit/node/themes/types'
import {Result, Checksum, Key, Theme, ThemeAsset} from '@shopify/cli-kit/node/themes/types'

export type ThemeParams = Partial<Pick<Theme, 'name' | 'role' | 'processing'>>
export type AssetParams = Partial<Pick<ThemeAsset, 'key' | 'value'>>
export type AssetParams = Pick<ThemeAsset, 'key'> & Partial<Pick<ThemeAsset, 'value' | 'attachment'>>

export async function fetchTheme(id: number, session: AdminSession): Promise<Theme | undefined> {
const response = await request('GET', `/themes/${id}`, session, undefined, {fields: 'id,name,role,processing'})
Expand Down Expand Up @@ -51,13 +51,9 @@ export async function bulkUploadThemeAssets(
id: number,
assets: AssetParams[],
session: AdminSession,
): Promise<BulkUploadResult[]> {
): Promise<Result[]> {
const response = await request('PUT', `/themes/${id}/assets/bulk`, session, {assets})
const bulkResults = response.json.results

if (bulkResults?.length > 0) return bulkResults.map(buildBulkUploadResults)

return []
return buildBulkUploadResults(response.json.results, assets)
}

export async function fetchChecksums(id: number, session: AdminSession): Promise<Checksum[]> {
Expand Down
33 changes: 21 additions & 12 deletions packages/cli-kit/src/public/node/themes/factories.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {BulkUploadResult, Checksum, Theme, ThemeAsset} from '@shopify/cli-kit/node/themes/types'
import {AssetParams} from './api.js'
import {Result, Checksum, Theme, ThemeAsset, Operation} from '@shopify/cli-kit/node/themes/types'

interface RemoteThemeResponse {
id: number
Expand All @@ -15,10 +16,9 @@ interface RemoteAssetResponse {
value: string
}

interface RemoteBulkUploadResponse {
body: {asset: RemoteAssetResponse}
export interface RemoteBulkUploadResponse {
body: {asset?: RemoteAssetResponse; errors?: {asset: string[]}}
code: number
errors?: string[]
}

export function buildTheme(themeJson?: RemoteThemeResponse): Theme | undefined {
Expand Down Expand Up @@ -52,13 +52,22 @@ export function buildThemeAsset(asset?: RemoteAssetResponse): ThemeAsset | undef
return {key, checksum, attachment, value}
}

export function buildBulkUploadResults(bulkUpload?: RemoteBulkUploadResponse): BulkUploadResult | undefined {
if (!bulkUpload) return
export function buildBulkUploadResults(
bulkUploadResponse: RemoteBulkUploadResponse[],
assets: AssetParams[],
): Result[] {
const results: Result[] = []
if (!bulkUploadResponse) return results

return {
key: bulkUpload.body.asset.key,
success: bulkUpload.code === 200,
errors: bulkUpload.errors || [],
asset: bulkUpload.body.asset || {},
}
bulkUploadResponse.forEach((bulkUpload, index) => {
const asset = assets[index]
results.push({
key: asset?.key || '',
success: bulkUpload.code === 200,
errors: bulkUpload.body.errors || {},
asset: bulkUpload.body.asset,
operation: Operation.Upload,
})
})
return results
}
8 changes: 4 additions & 4 deletions packages/cli-kit/src/public/node/themes/theme-manager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import {generateThemeName} from '../../../private/node/themes/generate-theme-nam
import {AdminSession} from '@shopify/cli-kit/node/session'
import {BugError} from '@shopify/cli-kit/node/error'
import {Theme} from '@shopify/cli-kit/node/themes/types'
import {DEVELOPMENT_THEME_ROLE} from '@shopify/cli-kit/node/themes/utils'
import {DEVELOPMENT_THEME_ROLE, Role} from '@shopify/cli-kit/node/themes/utils'

export abstract class ThemeManager {
protected themeId: string | undefined
Expand Down Expand Up @@ -32,9 +32,9 @@ export abstract class ThemeManager {
return theme
}

private async create() {
const name = generateThemeName(this.context)
const role = DEVELOPMENT_THEME_ROLE
async create(themeRole?: Role, themeName?: string) {
const name = themeName || generateThemeName(this.context)
const role = themeRole || DEVELOPMENT_THEME_ROLE
const theme = await createTheme(
{
name,
Expand Down
26 changes: 18 additions & 8 deletions packages/cli-kit/src/public/node/themes/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,28 +79,38 @@ export interface ThemeAsset extends Checksum {
}

/**
* Represents a single result returned within the response of a bulk upload operation.
* Each result includes the unique identifier for the file being uploaded,
* the status of the upload operation, any errors that occurred, and the asset that was uploaded.
* Represents a single result for a upload or delete operation on a single file
* Each result includes the unique identifier for the file, the type of the operation,
* the sucesss status of the operation, any errors that occurred, and the asset value of the file.
*/
export interface BulkUploadResult {
export interface Result {
/**
* The unique identifier for the file being uploaded.
*/
key: string

/**
* The operation associated with the result.
*/
operation: Operation

/* *
* Indicates whether the upload operation for this file was successful.
*/
success: boolean

/**
* An array of error messages that were generated during the upload operation for this file.
* Error message that was generated during the upload operation for this file.
*/
errors?: string[]
errors?: {asset?: string[]}

/**
/* *
* The asset that was uploaded as part of the upload operation for this file.
*/
asset: ThemeAsset
asset?: ThemeAsset
}

export enum Operation {
Delete = 'DELETE',
Upload = 'UPLOAD',
}
4 changes: 4 additions & 0 deletions packages/cli-kit/src/public/node/themes/utils.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
import {Theme} from '@shopify/cli-kit/node/themes/types'

export const DEVELOPMENT_THEME_ROLE = 'development'
export const LIVE_THEME_ROLE = 'live'
export const UNPUBLISHED_THEME_ROLE = 'unpublished'

export type Role = typeof DEVELOPMENT_THEME_ROLE | typeof LIVE_THEME_ROLE | typeof UNPUBLISHED_THEME_ROLE

export function isDevelopmentTheme(theme: Theme) {
return theme.role === DEVELOPMENT_THEME_ROLE
Expand Down
Loading

0 comments on commit f8ed8f9

Please sign in to comment.