mcpField
C
ce-setup

ce-setup

github.com/commercengine开发036 次安装9 周前更新
代码仓库

关于 ce-setup

面向开发者的 Commerce Engine SDK 设置技能,帮助根据项目框架配置店面 SDK。内容涵盖初始化、环境变量、会话存储,以及公开读取与会话操作的访问方式。

主要功能

  1. 01识别项目框架并选择入口
  2. 02安装并初始化店面 SDK
  3. 03配置环境变量和会话存储
  4. 04区分公开读取与会话流程
  5. 05说明 Hosted Checkout 令牌同步

适用场景

  1. 01为 Next.js 或 SPA 配置 SDK
  2. 02为 SSR 框架设置服务端会话
  3. 03将 Hosted Checkout 接入店面 SDK

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/commercengine/skills --skill ce-setup

安装后在 Claude Code 中输入/ce-setup确认已加载。

附带文件.claude-plugin/plugin.json.cursor-plugin/plugin.json

详细介绍

LLM Docs 标头:所有发送到 https://llm-docs.commercengine.io 的请求必须包含 Accept: text/markdown 标头(或在 URL 路径末尾追加 .md)。若未包含该标头,响应将返回 HTML,而不是可解析的 Markdown。

设置 Commerce Engine

此技能用于设置最新版 Commerce Engine SDK。

当前心智模型

所有框架均安装 @commercengine/storefront——一个带有子路径导出的统一软件包:

  • SPA:import { createStorefront } from "@commercengine/storefront" → storefront.public() / storefront.session()
  • Next.js:import { createNextjsStorefront } from "@commercengine/storefront/nextjs" → storefront.publicStorefront() / storefront.clientStorefront() / await storefront.serverStorefront()
  • TanStack Start:import { createTanStackStartStorefront } from "@commercengine/storefront/tanstack-start" → storefront.publicStorefront() / storefront.clientStorefront() + 单独的服务端入口,用于 serverStorefront()
  • Astro:import { createAstroStorefront } from "@commercengine/storefront/astro" → storefront.publicStorefront() / storefront.clientStorefront() + 单独的服务端入口,用于 serverStorefront(cookies)
  • SvelteKit:import { createSvelteKitStorefront } from "@commercengine/storefront/sveltekit" → storefront.publicStorefront() / storefront.clientStorefront() + 单独的服务端入口,用于 serverStorefront(cookies)

快速参考

步骤操作
1. 检测框架检查 package.json 和配置文件
2. 安装 SDK@commercengine/storefront(适用于所有框架)
3. 初始化 storefrontSPA:createStorefront(...),Next.js:createNextjsStorefront(...),TanStack Start:createTanStackStartStorefront(...),Astro:createAstroStorefront(...),SvelteKit:createSvelteKitStorefront(...)
4. 设置环境变量Next.js:NEXT_PUBLIC_*,TanStack Start / SPA:VITE_*,Astro / SvelteKit:PUBLIC_*
5. 引导会话SPA:如果希望在启动时预先设置会话,请调用一次 sdk.ensureAccessToken();SSR 框架:在客户端组件中调用 storefront.bootstrap()
6. 使用正确的访问器公共读取:publicStorefront() / public();会话流程:clientStorefront() / serverStorefront() / session()
7. 托管结账(如使用)必需:设置 authMode: "provided" 并进行双向令牌同步(适用于任何使用 Storefront SDK 的应用)

标准设置(Storefront + 托管结账)

如果应用在使用 Storefront SDK 的同时也使用托管结账,则必须设置 authMode: "provided" 并进行双向令牌同步,不能省略。SDK 会为 API 调用管理自己的会话;若不使用 provided 模式,结账会创建另一个独立会话。标准设置如下:

  • Storefront SDK 管理会话状态。
  • 托管结账以 authMode: "provided" 模式运行。
  • 在应用启动时初始化一次结账,而不是针对每个路由或组件渲染都初始化。
  • 双向令牌同步是必需的:
    • SDK -> 结账,通过 updateTokens(...)
    • 结账 -> SDK,通过 onTokensUpdated
import {
  BrowserTokenStorage,
  createStorefront,
} from "@commercengine/storefront";
import { getCheckout, initCheckout } from "@commercengine/checkout";

const tokenStorage = new BrowserTokenStorage("myapp_");

export const storefront = createStorefront({
  storeId: import.meta.env.VITE_STORE_ID,
  apiKey: import.meta.env.VITE_API_KEY,
  session: {
    tokenStorage,
    // Note: in SPA (createStorefront), onTokensUpdated is nested inside `session`.
    // In SSR wrappers (createNextjsStorefront / createTanStackStartStorefront),
    // it is a top-level config property — do not nest it under `session` there.
    onTokensUpdated: (accessToken, refreshToken) => {
      getCheckout().updateTokens(accessToken, refreshToken);
    },
  },
});

const sessionSdk = storefront.session();
const accessToken = await sessionSdk.ensureAccessToken();
const refreshToken = await tokenStorage.getRefreshToken();

initCheckout({
  storeId: import.meta.env.VITE_STORE_ID,
  apiKey: import.meta.env.VITE_API_KEY,
  authMode: "provided",
  accessToken: accessToken ?? undefined,
  refreshToken: refreshToken ?? undefined,
  onTokensUpdated: ({ accessToken, refreshToken }) => {
    void sessionSdk.setTokens(accessToken, refreshToken);
  },
});

框架检测

检查 package.json 和配置文件以识别框架:

指示项框架导入路径会话存储
依赖项中有 next,且有 next.config.*Next.js@commercengine/storefront/nextjs内置(基于 cookie)
依赖项中有 @tanstack/react-startTanStack Start@commercengine/storefront/tanstack-start内置(基于 cookie)
依赖项中有 astroAstro@commercengine/storefront/astro内置(基于 cookie)
依赖项中有 @sveltejs/kitSvelteKit@commercengine/storefront/sveltekit内置(基于 cookie)
依赖项中有 nuxtNuxt@commercengine/storefront + @commercengine/ssr-utilsServerTokenStorage
有 vite.config.* + 浏览器应用React / Vue / Svelte / Solid SPA@commercengine/storefrontBrowserTokenStorage
依赖项中有 expressExpress / Node.js@commercengine/storefrontMemoryTokenStorage 或自定义 TokenStorage
以上皆无Vanilla JS@commercengine/storefrontBrowserTokenStorage

决策树

User Request: "Set up Commerce Engine" / "Add e-commerce"
    │
    ├─ Read package.json + config files
    │
    ├─ Next.js detected?
    │   ├─ YES → Install @commercengine/storefront
    │   │        → Use createNextjsStorefront() from @commercengine/storefront/nextjs
    │   │        → Root layout uses storefront.publicStorefront() + StorefrontBootstrap
    │   │        → See ce-ssr-patterns for request-bound usage
    │   └─ NO ↓
    │
    ├─ TanStack Start detected?
    │   ├─ YES → Install @commercengine/storefront
    │   │        → Use createTanStackStartStorefront() from @commercengine/storefront/tanstack-start
    │   │        → Server-only: createTanStackStartServerStorefront() from .../tanstack-start/server
    │   └─ NO ↓
    │
    ├─ Astro detected?
    │   ├─ YES → Install @commercengine/storefront
    │   │        → Use createAstroStorefront() from @commercengine/storefront/astro
    │   │        → Server-only: createAstroServerStorefront() from .../astro/server
    │   └─ NO ↓
    │
    ├─ SvelteKit detected?
    │   ├─ YES → Install @commercengine/storefront
    │   │        → Use createSvelteKitStorefront() from @commercengine/storefront/sveltekit
    │   │        → Server-only: createSvelteKitServerStorefront() from .../sveltekit/server
    │   └─ NO ↓
    │
    ├─ Other SSR framework (Nuxt)?
    │   ├─ YES → Install @commercengine/storefront + @commercengine/ssr-utils
    │   │        → Use ServerTokenStorage with CookieAdapter
    │   └─ NO  → Install @commercengine/storefront
    │            → Use BrowserTokenStorage (SPA) or MemoryTokenStorage (Node)
    │
    ├─ Using Hosted Checkout?
    │   ├─ YES → Install @commercengine/checkout
    │   │        → authMode: "provided"
    │   │        → Two-way token sync (SDK ↔ checkout)
    │   └─ NO → SDK-only setup
    │
    └─ Create one storefront factory and use the framework-appropriate accessors

按框架设置

Next.js(App Router)
npm install @commercengine/storefront
// lib/storefront.ts
import { Environment } from "@commercengine/storefront";
import { createNextjsStorefront } from "@commercengine/storefront/nextjs";

export const storefront = createNextjsStorefront({
  storeId: process.env.NEXT_PUBLIC_STORE_ID!,
  apiKey: process.env.NEXT_PUBLIC_API_KEY!,
  environment: Environment.Staging,
  tokenStorageOptions: { prefix: "myapp_" },
});
// components/storefront-bootstrap.tsx
"use client";

import { useEffect } from "react";
import { storefront } from "@/lib/storefront";

export function StorefrontBootstrap() {
  useEffect(() => {
    storefront.bootstrap().catch(console.error);
  }, []);
  return null;
}

根布局是一个 Server Component,但可以将 StorefrontBootstrap(Client Component)作为子组件渲染——这是标准的 Next.js 组合方式。尽可能将引导组件放在组件树的高层。

// app/layout.tsx (Server Component — this is fine)
import { storefront } from "@/lib/storefront";
import { StorefrontBootstrap } from "@/components/storefront-bootstrap";

const { data: storeConfig } = await storefront.publicStorefront().store.getStoreConfig();

export default function RootLayout({ children }: { children: React.ReactNode }) {
  return (
    <html lang="en">
      <body>
        <StorefrontBootstrap />
        <header>{storeConfig?.store_config?.brand.name}</header>
        {children}
      </body>
    </html>
  );
}

如需了解完整的 Next.js 请求模型,请参阅 ce-ssr-patterns。

使用托管结账? 请参阅 ce-cart-checkout 和 references/hosted-checkout.md,了解令牌同步模式。

# .env.local
NEXT_PUBLIC_STORE_ID=your-store-id
NEXT_PUBLIC_API_KEY=your-api-key
TanStack Start
npm install @commercengine/storefront
// lib/storefront.ts
import { Environment } from "@commercengine/storefront";
import { createTanStackStartStorefront } from "@commercengine/storefront/tanstack-start";

export const storefrontConfig = {
  storeId: import.meta.env.VITE_STORE_ID,
  apiKey: import.meta.env.VITE_API_KEY,
  environment: Environment.Staging,
  tokenStorageOptions: { prefix: "myapp_" },
};

export const storefront = createTanStackStartStorefront(storefrontConfig);
// lib/storefront.server.ts (server-only module)
import { createTanStackStartServerStorefront } from "@commercengine/storefront/tanstack-start/server";
import { storefrontConfig } from "./storefront";

const serverStorefrontFactory = createTanStackStartServerStorefront(storefrontConfig);

export function serverStorefront() {
  return serverStorefrontFactory.serverStorefront();
}
// components/storefront-bootstrap.tsx
import { useEffect } from "react";
import { storefront } from "@/lib/storefront";

export function StorefrontBootstrap() {
  useEffect(() => {
    storefront.bootstrap().catch(console.error);
  }, []);
  return null;
}

在根布局(__root.tsx)中挂载 StorefrontBootstrap。

# .env
VITE_STORE_ID=your-store-id
VITE_API_KEY=your-api-key
Astro
npm install @commercengine/storefront
// src/lib/storefront-config.ts
import { Environment } from "@commercengine/storefront";
import type { AstroStorefrontConfig } from "@commercengine/storefront/astro";

export const storefrontConfig: AstroStorefrontConfig = {
  storeId: import.meta.env.PUBLIC_STORE_ID,
  apiKey: import.meta.env.PUBLIC_API_KEY,
  environment: Environment.Staging,
  tokenStorageOptions: { prefix: "myapp_" },
};
// src/lib/storefront.ts
import { createAstroStorefront } from "@commercengine/storefront/astro";
import { storefrontConfig } from "./storefront-config";

export const storefront = createAstroStorefront(storefrontConfig);
// src/lib/server-storefront.ts (server-only)
import { createAstroServerStorefront } from "@commercengine/storefront/astro/server";
import { storefrontConfig } from "./storefront-config";

export const serverStorefront = createAstroServerStorefront(storefrontConfig);

在根布局脚本中进行引导,然后在 SSR 页面/API 路由中使用 serverStorefront.serverStorefront(Astro.cookies)。

如需了解完整的 Astro 请求模型,请参阅 ce-ssr-patterns。

# .env
PUBLIC_STORE_ID=your-store-id
PUBLIC_API_KEY=your-api-key
SvelteKit
npm install @commercengine/storefront
// src/lib/storefront-config.ts
import { Environment } from "@commercengine/storefront";
import type { SvelteKitStorefrontConfig } from "@commercengine/storefront/sveltekit";
import { env } from "$env/static/public";

export const storefrontConfig: SvelteKitStorefrontConfig = {
  storeId: env.PUBLIC_STORE_ID,
  apiKey: env.PUBLIC_API_KEY,
  environment: Environment.Staging,
  tokenStorageOptions: { prefix: "myapp_" },
};
// src/lib/storefront.ts
import { createSvelteKitStorefront } from "@commercengine/storefront/sveltekit";
import { storefrontConfig } from "./storefront-config";

export const storefront = createSvelteKitStorefront(storefrontConfig);
// src/lib/server/storefront.ts (server-only — $lib/server/ is enforced by SvelteKit)
import { createSvelteKitServerStorefront } from "@commercengine/storefront/sveltekit/server";
import { storefrontConfig } from "$lib/storefront-config";

export const serverStorefront = createSvelteKitServerStorefront(storefrontConfig);

通过 onMount 在根 +layout.svelte 中进行引导,然后在服务器加载函数、钩子和操作中使用 serverStorefront.serverStorefront(cookies)。

如需了解完整的 SvelteKit 请求模型,请参阅 ce-ssr-patterns。

# .env
PUBLIC_STORE_ID=your-store-id
PUBLIC_API_KEY=your-api-key
React / Vue / Svelte / Solid(SPA)
npm install @commercengine/storefront
// lib/storefront.ts
import {
  BrowserTokenStorage,
  Environment,
  createStorefront,
} from "@commercengine/storefront";

export const storefront = createStorefront({
  storeId: import.meta.env.VITE_STORE_ID,
  environment: import.meta.env.PROD ? Environment.Production : Environment.Staging,
  apiKey: import.meta.env.VITE_API_KEY,
  session: {
    tokenStorage: new BrowserTokenStorage("myapp_"),
  },
});
// Public reads
const { data: products } = await storefront.public().catalog.listProducts();

// Live session flows
const sessionSdk = storefront.session();
await sessionSdk.ensureAccessToken();
# .env
VITE_STORE_ID=your-store-id
VITE_API_KEY=your-api-key
Node.js / Express
npm install @commercengine/storefront
import {
  Environment,
  MemoryTokenStorage,
  createStorefront,
} from "@commercengine/storefront";

export const storefront = createStorefront({
  storeId: process.env.CE_STORE_ID!,
  environment: process.env.NODE_ENV === "production" ? Environment.Production : Environment.Staging,
  apiKey: process.env.CE_API_KEY!,
  session: {
    tokenStorage: new MemoryTokenStorage(),
  },
});

会话存储指南

存储使用场景持久性SSR 安全
BrowserTokenStorage浏览器 SPAlocalStorage否
CookieTokenStorage浏览器 cookie / 跨标签页 cookie 同步Cookies仅限浏览器
MemoryTokenStorage服务端或临时存储内存中是
ServerTokenStorage使用请求 cookie 的 SSR 框架通过框架适配器使用 Cookies是

对于实时 SSR 请求流程,请使用 @commercengine/ssr-utils 中的 ServerTokenStorage。不要将 CookieTokenStorage 用作 SSR 服务端的主要存储层。

首次 API 调用

可立即执行公开读取操作:

const { data: products } = await storefront.public().catalog.listProducts();

如果应用需要提前创建实时匿名/已登录会话,请在启动期间执行一次:

const sessionSdk = storefront.session();
await sessionSdk.ensureAccessToken();
const { data: wishlist } = await sessionSdk.cart.getWishlist();

常规的会话感知型 SDK 方法,例如 sdk.cart.getWishlist()、sdk.cart.addToWishlist()、sdk.cart.getUserCart() 和 sdk.customer.listAddresses(),无需手动调用 ensureAccessToken()。中间件和重载会自动处理会话创建和 ID 解析。如果应用需要提前引导,请在启动期间调用一次,而不要在各处功能代码中散布 ensureAccessToken()。

Session 辅助方法

大多数需要 user_id 或 customer_id 的会话 SDK 方法都有无参数重载,可从当前会话中自动解析。你无需手动获取 ID 并传入。例如:

// Preferred — SDK auto-resolves user_id from session
const { data } = await sdk.cart.getUserCart();
const { data: wishlist } = await sdk.cart.getWishlist();
const { data: orders } = await sdk.order.listOrders();
const { data: addresses } = await sdk.customer.listAddresses();

// Only pass IDs explicitly when operating on behalf of a different user (admin scenarios)
const { data } = await sdk.cart.getUserCart({ user_id: "other_user_id" });

具有无参数重载的方法(自动解析 user_id 或 customer_id):

  • 购物车:getUserCart()、deleteUserCart()、getWishlist()、addToWishlist()、removeFromWishlist()
  • 订单:listOrders()
  • 客户:listAddresses()、createAddress()、getAddress()、updateAddress()、deleteAddress()、getLoyaltyDetails()、listLoyaltyPointsActivity()、listCustomerReviews()、listSavedPaymentMethods()、listCustomerCards()

Auth 客户端方法仍需要显式 ID——getUserDetails({ id })、updateUserDetails({ id }) 等。对于这些调用,请使用 sdk.getUserId() 获取当前用户的 ID。

仍需要会话辅助方法的情况
辅助方法使用时机
ensureAccessToken()在启动期间调用一次,以便在你明确希望提前建立会话时使用
getAccessToken()被动读取当前令牌(传入 Hosted Checkout 初始化流程)
sdk.session.peekRefreshToken()被动读取当前刷新令牌(传入 Hosted Checkout 初始化流程)
setTokens(accessToken, refreshToken?)将 Hosted Checkout 中的令牌同步回 SDK
getUserId()传入需要显式 { id } 的 Auth 客户端方法
getUserInfo()读取用户信息以用于 UI 显示(姓名、邮箱),无需调用 API——从 JWT 解码
isLoggedIn() / isAnonymous()条件式 UI 渲染(显示登录按钮或账户菜单)
sdk.session——Peek 与 Ensure

session 属性提供两种模式,可进行精细控制:

Peek——被动读取,不会创建会话或刷新令牌,失败时返回 null:

  • sdk.session.peekAccessToken() / peekRefreshToken() / peekUserInfo() / peekUserId() / peekCustomerId()

Ensure——可能会创建匿名会话或刷新过期令牌,失败时抛出异常:

  • sdk.session.ensureAccessToken() / ensureUserInfo() / ensureUserId() / ensureCustomerId()

如果你想在不产生副作用的情况下获取当前状态(例如,将令牌传入 Hosted Checkout 初始化流程),请使用 peek。如果在进行任何其他会话调用之前,你明确需要有效令牌或身份信息,请使用 ensure。大多数购物车、订单和客户方法已在内部处理这些操作。

环境变量

变量必需说明
CE_STORE_ID / NEXT_PUBLIC_STORE_ID是你的商店标识符
CE_API_KEY / NEXT_PUBLIC_API_KEY是Storefront API 密钥
CE_ENVIRONMENT / NEXT_PUBLIC_ENVIRONMENT否staging 或 production

默认请求头

SDK 在配置中支持 defaultHeaders。这对拥有客户群组、且价格和促销因群组而异的 B2B 商店很有用。

const storefront = createStorefront({
  storeId: "...",
  apiKey: "...",
  defaultHeaders: {
    customer_group_id: "01JHS28V83KDWTRBXXJQRTEKA0",
  },
  session: {
    tokenStorage: new BrowserTokenStorage("myapp_"),
  },
});

登录后,根据用户资料或 Auth 响应设置 customer_group_id。相关目录方法会自动接收此值。

分析

分析在服务端进行并自动处理。Commerce Engine 按照 Segment 规范收集电商事件。商家可通过 Admin 集成将这些事件路由到 Segment、Rudderstack 或类似工具。商店前端代码无需手动接入分析功能。

常见问题

级别问题解决方案
高在购物车/身份验证/客户/订单流程中使用 public()对任何实时用户或匿名会话操作,都使用 session()
高将 CookieTokenStorage 用作 SSR 服务端存储使用 @commercengine/ssr-utils 中的 ServerTokenStorage,或使用 Next.js / TanStack Start 的内置包装器
高在 SSR 应用中跳过 StorefrontBootstrap在根布局中挂载一个调用 storefront.bootstrap() 一次的客户端组件
中在构建/预渲染代码中初始化匿名身份验证改用 public()
中在公共客户端和会话客户端之间重复配置优先使用一个 createStorefront(...) 工厂

另请参阅

  • ssr-patterns/ - Next.js 和 TanStack Start 的 publicStorefront() / clientStorefront() / serverStorefront() 模式
  • ssr/ - 使用 @commercengine/ssr-utils 的自定义 SSR 绑定(Nuxt 和其他不受支持的框架)
  • auth/ - 身份验证流程
  • cart-checkout/ - Hosted Checkout 同步模式

文档

评论

支持 Markdown