212 lines
8.0 KiB
TypeScript

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) }],
};
},
},
];