type GraphqlResponse = { data?: T; errors?: unknown; }; const shop = requiredEnv("SHOPIFY_SHOP_DOMAIN"); const token = requiredEnv("SHOPIFY_ADMIN_ACCESS_TOKEN"); const endpoint = `https://${shop}/admin/api/2026-01/graphql.json`; const definitionMutation = `#graphql mutation DreameMetaobjectDefinitionCreate($definition: MetaobjectDefinitionCreateInput!) { metaobjectDefinitionCreate(definition: $definition) { metaobjectDefinition { id type } userErrors { field message } } } `; const metaobjectMutation = `#graphql mutation DreameMetaobjectCreate($metaobject: MetaobjectCreateInput!) { metaobjectCreate(metaobject: $metaobject) { metaobject { id handle } userErrors { field message } } } `; async function main() { await graphql(definitionMutation, { definition: { type: "dreame_activity", name: "Dreame Activity", access: { storefront: "NONE" }, fieldDefinitions: [ { key: "activity_id", name: "Activity ID", type: "number_integer", required: true }, { key: "api_app_id", name: "API App ID", type: "single_line_text_field", required: true }, { key: "api_secret", name: "API Secret", type: "single_line_text_field", required: true }, { key: "status_api_url", name: "Status API URL", type: "url", required: true }, { key: "push_api_url", name: "Push API URL", type: "url", required: true }, { key: "redirect_url", name: "Redirect URL", type: "url", required: true }, { key: "button_text", name: "Button Text", type: "json", required: true }, { key: "shop", name: "Shop Override", type: "single_line_text_field", required: false }, ], }, }); await graphql(metaobjectMutation, { metaobject: { type: "dreame_activity", handle: "dreame-activity-config", fields: [ { key: "activity_id", value: "12" }, { key: "api_app_id", value: "mock-app-id" }, { key: "api_secret", value: "mock-secret" }, { key: "status_api_url", value: "https://third-party.example/status" }, { key: "push_api_url", value: "https://third-party.example/push" }, { key: "redirect_url", value: "https://activity.example.com" }, { key: "button_text", value: JSON.stringify({ en: "Claim Your Reward", "zh-CN": "领取奖励" }) }, { key: "shop", value: shop }, ], }, }); } async function graphql(query: string, variables: Record): Promise> { const response = await fetch(endpoint, { method: "POST", headers: { "Content-Type": "application/json", "X-Shopify-Access-Token": token, }, body: JSON.stringify({ query, variables }), }); const payload = (await response.json()) as GraphqlResponse; if (!response.ok || payload.errors) { throw new Error(JSON.stringify(payload.errors || payload)); } console.log(JSON.stringify(payload, null, 2)); return payload; } function requiredEnv(name: string): string { const value = process.env[name]; if (!value) { throw new Error(`${name} is required`); } return value; } main().catch((error) => { console.error(error); process.exit(1); });