npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@cnr-mtsn/shopify

v2.0.6

Published

Shopify extension migration tool — Unified migration for Functions and UI Extensions to 2026-01 API version

Readme

Shopify Extensions Migration Tool

A unified CLI tool for migrating Shopify extensions to API version 2026-01. Handles both Shopify Functions (purchase.* → cart.* targets) and UI Extensions (React → Preact with Polaris web components).

Table of Contents


Overview

As of API version 2025-10/2026-01, Shopify has made significant changes to both Functions and UI Extensions:

| Extension Type | Key Changes | |---------------|-------------| | Functions | Target paths changed from purchase.* to cart.*, operation keys renamed, output structures changed | | UI Extensions | React deprecated in favor of Preact, React components replaced with Polaris web components (<s-*> elements), hooks replaced with global shopify object |

This tool automates these migrations interactively, allowing you to review and approve changes for each extension before they're applied.


Installation

Local Usage (Recommended)

# Clone or navigate to the tools directory
cd /path/to/tools/extensions-migration

# No dependencies required - uses Node.js built-ins only
node migrate-extensions.js --help

Global Installation

# From the extensions-migration directory
npm link

# Now available globally
migrate-extensions --help

Requirements

  • Node.js 18.x or higher
  • A Shopify app with extensions in an extensions/ directory

Quick Start

# Navigate to your Shopify app root (where extensions/ folder is located)
cd /path/to/your-shopify-app

# Run the migration tool (interactive mode)
node /path/to/migrate-extensions.js

# Or if installed globally
migrate-extensions

The tool will:

  1. Scan for all extensions in ./extensions/
  2. Show what changes will be made for each extension
  3. Ask for your approval before applying changes
  4. Generate a migration.json log file

Usage

node migrate-extensions.js [path] [options]

Arguments

| Argument | Description | |----------|-------------| | [path] | Path to extensions directory or specific extension. Defaults to ./extensions/ |

Options

| Option | Description | |--------|-------------| | --dry-run | Preview changes without writing any files | | --auto-approve | Skip confirmation prompts (use with caution) | | --api-version <version> | Target API version (default: 2026-01) | | --force | Re-migrate source files even if already at target API version |

Examples

# Interactive migration of all extensions
node migrate-extensions.js

# Preview changes only (no files modified)
node migrate-extensions.js --dry-run

# Migrate specific extension
node migrate-extensions.js extensions/my-checkout-extension

# Migrate without prompts (for CI/CD)
node migrate-extensions.js --auto-approve

# Combine options
node migrate-extensions.js ./extensions --dry-run --auto-approve

# Target a different API version
node migrate-extensions.js --api-version 2025-10

# Re-migrate source files even if TOML shows target version
# Useful if initial migration missed some files
node migrate-extensions.js --force

What Gets Migrated

Functions

Target Path Transformations

| Old Target | New Target | |------------|------------| | purchase.payment-customization.run | cart.payment-methods.transform.run | | purchase.shipping-discount.run | cart.delivery-options.discounts.generate.run | | purchase.product-discount.run | cart.lines.discounts.generate.run | | purchase.order-discount.run | cart.lines.discounts.generate.run | | purchase.cart-transform.run | cart.transform.run | | purchase.delivery-customization.run | cart.delivery-options.transform.run | | purchase.delivery-customization.fetch | cart.delivery-options.transform.fetch | | purchase.fulfillment-constraint-rule.run | cart.fulfillment-constraints.generate.run | | purchase.order-routing-location-rule.run | cart.fulfillment-groups.location-rankings.generate.run | | purchase.validation.run | cart.validations.generate.run | | purchase.validation.fetch | cart.validations.generate.fetch |

File Changes

| File | Changes | |------|---------| | shopify.extension.toml | target, input_query, export, api_version updated | | package.json | javy dependency removed | | src/run.graphql | Renamed to src/{snake_case_target}.graphql, query name updated | | src/run.js | Renamed to src/{snake_case_target}.js, function name and types updated | | src/run.test.js | Renamed, imports and function calls updated | | src/index.js | Re-export path updated |

Operation Key Renames

Payment Customization:

// Before                    // After
{ hide: {...} }        →     { paymentMethodHide: {...} }
{ move: {...} }        →     { paymentMethodMove: {...} }
{ rename: {...} }      →     { paymentMethodRename: {...} }

Delivery Customization:

// Before                    // After
{ hide: {...} }        →     { deliveryOptionHide: {...} }
{ move: {...} }        →     { deliveryOptionMove: {...} }
{ rename: {...} }      →     { deliveryOptionRename: {...} }

Cart Transform:

// Before                    // After
{ expand: {...} }      →     { lineExpand: {...} }
{ merge: {...} }       →     { linesMerge: {...} }
{ update: {...} }      →     { lineUpdate: {...} }

Shipping Discount Output Restructuring

// Before (flat structure)
return {
  discounts: [{
    value: { percentage: { value: 10 } },
    targets: [{ deliveryOption: { handle: "..." } }],
    message: "10% off shipping"
  }]
};

// After (nested structure)
return {
  operations: [{
    deliveryDiscountsAdd: {
      selectionStrategy: "ALL",
      candidates: [{
        targets: [{ deliveryOption: { handle: "..." } }],
        value: { percentage: { value: 10 } },
        message: "10% off shipping",
        associatedDiscountCode: null
      }]
    }
  }]
};

UI Extensions

Package.json Changes

// Before (React)
{
  "dependencies": {
    "react": "^18.0.0",
    "@shopify/ui-extensions": "2024.4.x",
    "@shopify/ui-extensions-react": "2024.4.x"
  },
  "devDependencies": {
    "@types/react": "^18.0.0",
    "react-reconciler": "0.29.0"
  }
}

// After (Preact)
{
  "dependencies": {
    "preact": "^10.10.0",
    "@preact/signals": "^2.3.0",
    "@shopify/ui-extensions": "2026.01.x"
  }
}

Note: The migration tool automatically runs npm install && npm prune to install new Preact packages and remove old React packages that are no longer needed.

Extension Registration

// Before (React)
import { reactExtension, TextField } from '@shopify/ui-extensions-react/checkout';

export default reactExtension(
  'purchase.checkout.block.render',
  () => <Extension />
);

// After (Preact)
import '@shopify/ui-extensions/preact';
import { render } from 'preact';

export default async () => {
  render(<Extension />, document.body);
};

Component Transformations

| React Component | Polaris Web Component | |-----------------|----------------------| | <TextField /> | <s-text-field /> | | <Checkbox /> | <s-checkbox /> | | <Button /> | <s-button /> | | <Banner /> | <s-banner /> | | <Text /> | <s-text /> | | <Heading /> | <s-heading /> | | <BlockStack /> | <s-stack direction="block" /> | | <InlineStack /> | <s-stack direction="inline" /> | | <View /> | <s-box /> | | <Select /> | <s-select /> | | <Image /> | <s-image /> | | <Link /> | <s-link /> | | <Spinner /> | <s-spinner /> | | <Divider /> | <s-divider /> | | <Grid /> | <s-grid /> | | <Modal /> | <s-modal /> |

Full component mapping in Shopify docs

Hook to API Transformations

// Before (React hooks)
const lines = useCartLines();
const settings = useSettings();
const translate = useTranslate();
const applyChange = useApplyAttributeChange();

// After (shopify global object)
const lines = shopify.lines.value;
const settings = shopify.settings.value;
const translate = shopify.i18n.translate;
await shopify.applyAttributeChange({...});

Event Handler Changes

// Before (React - value passed directly)
<TextField
  onChange={(value) => setValue(value)}
/>

// After (Preact - event object)
<s-text-field
  onInput={(e) => setValue(e.target.value)}
/>

Migration Log

After each run, the tool generates a migration.json file in the current directory:

{
  "startTime": "2026-02-04T20:16:24.335Z",
  "targetApiVersion": "2026-01",
  "dryRun": false,
  "extensions": [
    {
      "name": "my-checkout-extension",
      "path": "/path/to/extensions/my-checkout-extension",
      "migrated": true,
      "type": "ui_extension",
      "apiVersion": "2026-01",
      "changes": [
        { "file": "shopify.extension.toml", "desc": "api_version bumped to 2026-01" },
        { "file": "package.json", "desc": "removed react from dependencies" },
        { "file": "src/Checkout.jsx", "desc": "React → Preact migration" }
      ],
      "warnings": [
        "Manual review recommended: verify all API calls use global shopify object"
      ]
    }
  ],
  "endTime": "2026-02-04T20:16:24.348Z"
}

Post-Migration Steps

After running the migration tool, complete these steps:

For Functions

# Regenerate schema types for each function
cd extensions/my-function
shopify app function typegen

For UI Extensions

Note: The migration tool automatically runs npm install && npm prune to install the new Preact dependencies and remove old React packages.

# 1. Run dev to generate shopify.d.ts type definitions
shopify app dev

# 2. Build and verify
shopify app build

Manual Review Checklist

  • [ ] Verify all onChange handlers are converted to onInput with event object
  • [ ] Check that shopify.* API calls work correctly (not useApi() hooks)
  • [ ] Review component prop changes (e.g., statustone for Banner)
  • [ ] Test useBuyerJourneyIntercept conversions (now uses useEffect pattern)
  • [ ] Run tests: npm test
  • [ ] Test in development: shopify app dev

Examples

Example 1: Migrating a Single Extension

$ node migrate-extensions.js extensions/freight-account --dry-run

╭─────────────────────────────────────────────────────────╮
│  Shopify Extensions Migration Tool                       │
│  Functions & UI Extensions → API 2026-01                │
╰─────────────────────────────────────────────────────────╯

  Mode: DRY RUN — no files will be written

═══ UI Extension: freight-account ═══
  Type: ui_extension
  API version: 2025-01 → 2026-01
  Package version: → 2026.01.x

  Planned changes:
  →  shopify.extension.toml: api_version bumped to 2026-01
  →  package.json: removed react from dependencies
  →  package.json: added preact ^10.10.0
  →  src/Checkout.jsx: React → Preact migration

  Apply these changes? [y/n]:

Example 2: CI/CD Pipeline

# .github/workflows/migrate.yml
name: Migrate Extensions
on:
  workflow_dispatch:

jobs:
  migrate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Run Migration
        run: node tools/migrate-extensions.js --auto-approve

      - name: Commit Changes
        run: |
          git config user.name "GitHub Actions"
          git config user.email "[email protected]"
          git add -A
          git commit -m "chore: migrate extensions to 2026-01 API"
          git push

Troubleshooting

"No extensions found"

Make sure you're running the tool from your app's root directory (where extensions/ folder exists), or provide the correct path:

node migrate-extensions.js /path/to/your/app/extensions

"No migration mapping for target"

The extension is either:

  1. Already using the new cart.* target format (no migration needed)
  2. Using a target not yet supported by this tool

TypeScript errors after migration

Run shopify app dev to regenerate the shopify.d.ts type definitions file.

Component not rendering

Polaris web components require closing tags even when empty:

// Wrong
<s-text-field label="Name" />

// Correct
<s-text-field label="Name"></s-text-field>

Event handlers not working

Remember that Preact event handlers receive the event object, not the value directly:

// Before (React)
onChange={(value) => setValue(value)}

// After (Preact)
onInput={(e) => setValue(e.target.value)}

Reference Directories

This repository includes reference implementations:

| Directory | Description | |-----------|-------------| | old-api-version/ | Extensions using pre-2025-10 patterns (React, purchase.* targets) | | latest-api-version/ | Manually migrated extensions using 2026-01 patterns (Preact, cart.* targets) |

Use these as reference when reviewing your migrated code.


Deprecated Scripts

The following scripts are deprecated but still available for backwards compatibility:

  • upgrade-functions.js - Use migrate-extensions.js instead
  • upgrade-ui-extensions.js - Use migrate-extensions.js instead

Contributing

  1. Test changes against both old-api-version/ and latest-api-version/ directories
  2. Run with --dry-run first to verify output
  3. Update this README if adding new features

Resources