import { z } from 'zod'; import { ShopifyClient } from '../clients/shopify.js'; const ListThemesInput = z.object({ fields: z.string().optional().describe('Comma-separated list of fields to retrieve'), role: z.enum(['main', 'unpublished', 'demo']).optional().describe('Filter by theme role'), }); const GetThemeInput = z.object({ id: z.string().describe('Theme ID'), fields: z.string().optional().describe('Comma-separated list of fields to retrieve'), }); const CreateThemeInput = z.object({ name: z.string().describe('Theme name'), src: z.string().optional().describe('URL to theme ZIP file'), role: z.enum(['main', 'unpublished']).optional().describe('Theme role'), }); const UpdateThemeInput = z.object({ id: z.string().describe('Theme ID'), name: z.string().optional().describe('Theme name'), role: z.enum(['main', 'unpublished']).optional().describe('Theme role'), }); const DeleteThemeInput = z.object({ id: z.string().describe('Theme ID'), }); const ListAssetsInput = z.object({ theme_id: z.string().describe('Theme ID'), fields: z.string().optional().describe('Comma-separated list of fields to retrieve'), }); const GetAssetInput = z.object({ theme_id: z.string().describe('Theme ID'), asset_key: z.string().describe('Asset key (path, e.g., "templates/index.liquid")'), }); const CreateOrUpdateAssetInput = z.object({ theme_id: z.string().describe('Theme ID'), key: z.string().describe('Asset key (path, e.g., "templates/index.liquid")'), value: z.string().optional().describe('Asset text content'), src: z.string().optional().describe('Asset source URL (for binary assets)'), attachment: z.string().optional().describe('Base64-encoded binary asset content'), }); export default [ { name: 'shopify_list_themes', description: 'List all themes with optional role filtering', inputSchema: { type: 'object' as const, properties: { fields: { type: 'string', description: 'Comma-separated list of fields to retrieve' }, role: { type: 'string', enum: ['main', 'unpublished', 'demo'], description: 'Filter by theme role' }, }, }, handler: async (input: unknown, client: ShopifyClient) => { const validated = ListThemesInput.parse(input); const results = await client.list('/themes.json', { params: validated }); return { content: [{ type: 'text' as const, text: JSON.stringify(results, null, 2) }], }; }, }, { name: 'shopify_get_theme', description: 'Get a specific theme by ID', inputSchema: { type: 'object' as const, properties: { id: { type: 'string', description: 'Theme ID' }, fields: { type: 'string', description: 'Comma-separated list of fields to retrieve' }, }, required: ['id'], }, handler: async (input: unknown, client: ShopifyClient) => { const validated = GetThemeInput.parse(input); const result = await client.get(`/themes/${validated.id}.json`, { params: validated.fields ? { fields: validated.fields } : {}, }); return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], }; }, }, { name: 'shopify_create_theme', description: 'Create a new theme from a ZIP file', inputSchema: { type: 'object' as const, properties: { name: { type: 'string', description: 'Theme name' }, src: { type: 'string', description: 'URL to theme ZIP file' }, role: { type: 'string', enum: ['main', 'unpublished'], description: 'Theme role' }, }, required: ['name'], }, handler: async (input: unknown, client: ShopifyClient) => { const validated = CreateThemeInput.parse(input); const result = await client.create('/themes.json', { theme: validated }); return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], }; }, }, { name: 'shopify_update_theme', description: 'Update an existing theme', inputSchema: { type: 'object' as const, properties: { id: { type: 'string', description: 'Theme ID' }, name: { type: 'string', description: 'Theme name' }, role: { type: 'string', enum: ['main', 'unpublished'], description: 'Theme role' }, }, required: ['id'], }, handler: async (input: unknown, client: ShopifyClient) => { const validated = UpdateThemeInput.parse(input); const { id, ...updates } = validated; const result = await client.update(`/themes/${id}.json`, { theme: updates }); return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], }; }, }, { name: 'shopify_delete_theme', description: 'Delete a theme by ID', inputSchema: { type: 'object' as const, properties: { id: { type: 'string', description: 'Theme ID' }, }, required: ['id'], }, handler: async (input: unknown, client: ShopifyClient) => { const validated = DeleteThemeInput.parse(input); await client.delete(`/themes/${validated.id}.json`); return { content: [{ type: 'text' as const, text: `Theme ${validated.id} deleted successfully` }], }; }, }, { name: 'shopify_list_theme_assets', description: 'List all assets in a theme', inputSchema: { type: 'object' as const, properties: { theme_id: { type: 'string', description: 'Theme ID' }, fields: { type: 'string', description: 'Comma-separated list of fields to retrieve' }, }, required: ['theme_id'], }, handler: async (input: unknown, client: ShopifyClient) => { const validated = ListAssetsInput.parse(input); const { theme_id, ...params } = validated; const results = await client.list(`/themes/${theme_id}/assets.json`, { params }); return { content: [{ type: 'text' as const, text: JSON.stringify(results, null, 2) }], }; }, }, { name: 'shopify_get_theme_asset', description: 'Get a specific theme asset by key', inputSchema: { type: 'object' as const, properties: { theme_id: { type: 'string', description: 'Theme ID' }, asset_key: { type: 'string', description: 'Asset key (path, e.g., "templates/index.liquid")' }, }, required: ['theme_id', 'asset_key'], }, handler: async (input: unknown, client: ShopifyClient) => { const validated = GetAssetInput.parse(input); const result = await client.get(`/themes/${validated.theme_id}/assets.json`, { params: { 'asset[key]': validated.asset_key }, }); return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], }; }, }, { name: 'shopify_create_or_update_theme_asset', description: 'Create or update a theme asset (text or binary)', inputSchema: { type: 'object' as const, properties: { theme_id: { type: 'string', description: 'Theme ID' }, key: { type: 'string', description: 'Asset key (path, e.g., "templates/index.liquid")' }, value: { type: 'string', description: 'Asset text content' }, src: { type: 'string', description: 'Asset source URL (for binary assets)' }, attachment: { type: 'string', description: 'Base64-encoded binary asset content' }, }, required: ['theme_id', 'key'], }, handler: async (input: unknown, client: ShopifyClient) => { const validated = CreateOrUpdateAssetInput.parse(input); const { theme_id, ...assetData } = validated; const result = await client.update(`/themes/${theme_id}/assets.json`, { asset: assetData }); return { content: [{ type: 'text' as const, text: JSON.stringify(result, null, 2) }], }; }, }, ];