Skip to main content

sfnext-scapi

Use and extend SCAPI clients in a Storefront Next project: createApiClients, the `@/scapi` type barrel, typing `c_*` custom attributes by overriding a built-in client, and adding your own custom API end to end with `b2c sfnext scapi` (add, available, list, remove). Use for "clients.shopperProducts", "c_ attribute is not typed", "sfnext scapi add", "add custom API to the storefront", src/scapi/ generated files, custom-clients.ts, calling a loyalty/notify-style custom endpoint from a loader or action, useScapiFetcher, personalized=none for custom clients, or 404 from a custom endpoint. Do not use for writing the cartridge/schema.yaml itself (use `b2c:b2c-custom-api-development`), endpoint registration status (use `b2c-cli:b2c-scapi-custom`), loader/caching strategy (use `storefront-next:sfnext-data-fetching`), or login/session code (use `storefront-next:sfnext-authentication`).

معلومات المصدر

المستودع
SalesforceCommerceCloud/b2c-developer-tooling
آخر نشاط في المصدر
٤ أكتوبر ٢٠٢٦ في ١٦:٤٠
لغة SKILL.md المكتشفة
الإنجليزية
النجوم
٥٦
التفرعات
٢٢

خيارات التثبيت

يُحدَّد Prompt الذي يراجع المصدر أولًا بشكل افتراضي. يمكنك التبديل إلى أمر مباشر أو تنزيل نسخة محلية.

مراجعة ملفات المصدر

اقرأ SKILL.md وأي ملفات مرافقة يعرضها SkillsMP قبل أن تقرر التثبيت.

مستكشف الملفات
3 ملفات

عرض SKILL.md

SKILL.md
تعليمات المصدر · معاينة للقراءة فقط
name
sfnext-scapi
description
Use and extend SCAPI clients in a Storefront Next project: createApiClients, the `@/scapi` type barrel, typing `c_*` custom attributes by overriding a built-in client, and adding your own custom API end to end with `b2c sfnext scapi` (add, available, list, remove). Use for "clients.shopperProducts", "c_ attribute is not typed", "sfnext scapi add", "add custom API to the storefront", src/scapi/ generated files, custom-clients.ts, calling a loyalty/notify-style custom endpoint from a loader or action, useScapiFetcher, personalized=none for custom clients, or 404 from a custom endpoint. Do not use for writing the cartridge/schema.yaml itself (use `b2c:b2c-custom-api-development`), endpoint registration status (use `b2c-cli:b2c-scapi-custom`), loader/caching strategy (use `storefront-next:sfnext-data-fetching`), or login/session code (use `storefront-next:sfnext-authentication`).
# Storefront Next SCAPI Clients and Custom APIs The runtime (`@salesforce/storefront-next-runtime/scapi`) already ships typed clients for the standard shopper APIs (products, search, baskets, customers, orders, and so on). You do not "add" those. `sfnext scapi add` does one of two things on top: 1. **Override** a built-in client (client key matches, for example `shopperProducts`) with a richer schema, typically your tenant's schema expanded with `c_*` custom attributes, so `product.c_myAttr` is typed. 2. **Add a custom API** you deployed to B2C Commerce (a new property such as `clients.loyalty`). Which one you get is decided automatically from the client key. Deep dive: `docs/README-SCAPI.md` in your project. ## The CLI surface Run as `b2c sfnext scapi ...`, or inside your project as `pnpm sfnext scapi ...` (the `sfnext` bin ships with the project). Add `-d <dir>` / `--project-directory` to target another directory. | Command | What it does | |---|---| | `scapi available` | Probes your tenant: for each of the built-in shopper APIs counts `c_*` attributes, lists tenant custom APIs, and prints the matching `scapi add` command. Needs OAuth. No filter flags. | | `scapi add <apiFamily> <apiName> <apiVersion>` | Pull mode: fetch the schema from the SCAPI Schemas API. Needs OAuth. | | `scapi add --schema <file> --name <clientKey>` | Local mode: use a YAML/JSON OpenAPI file. `--name` is required here. | | `scapi list` | Shows registered Overrides and Custom APIs (schema, base path, locale). | | `scapi remove <clientKey>` | Removes the registration and its generated files (one positional argument: the client key, for example `loyalty`). | `add` flags: `--name <key>` (defaults to camelCase of the API name in pull mode), `--base-path <path>` (derived from the schema `servers[].url` if omitted), `--supports-locale` / `--no-supports-locale` (overrides inherit the built-in default), `--expand-custom-properties` (default on, pull mode only; include `c_*`, use `--no-expand-custom-properties` to skip). Re-running `add` regenerates; there is no `--force` and no `--json`. There is no install step after `add`. **Pull mode prerequisites:** SCAPI short code (`SFCC_SHORTCODE` or `--short-code`), tenant id (`SFCC_TENANT_ID` or `--tenant-id`), and an Account Manager API client allowed the `sfcc.scapi-schemas` scope (`SFCC_CLIENT_ID` and `SFCC_CLIENT_SECRET`, or `--client-id`/`--client-secret`, or `dw.json`). The legacy names `SFCC_OAUTH_CLIENT_ID` / `SFCC_OAUTH_CLIENT_SECRET` are also accepted because the CLI resolves both. If the `@salesforce/storefront-next-dev` package is in the project, `b2c` uses that local version. ```bash # Which built-in APIs have c_ attributes on my tenant? Which custom APIs exist? b2c sfnext scapi available # Type c_* attributes on products (override; pulls schema with custom properties) b2c sfnext scapi add product shopper-products v1 # Register a custom API from the tenant, or from a local file b2c sfnext scapi add custom loyalty v1 b2c sfnext scapi add --schema ./loyalty-api.yaml --name loyalty --base-path /custom/loyalty/v1 b2c sfnext scapi list b2c sfnext scapi remove loyalty ``` For a schema-only look without touching the project use `b2c scapi schemas get/list` (see `b2c-cli:b2c-scapi-schemas`; both need `--tenant-id`). ## What gets generated ``` src/scapi/ index.ts barrel (generated), the only SCAPI import surface for app code custom-clients.ts registry of overrides and custom clients (generated) schemas/ <name>-<ver>.yaml and .meta.json generated/ <name>-<ver>.ts, .operations.ts, (.namespace.ts for overrides) ``` Never hand-edit these; rerun `sfnext scapi add`. Registry entries carry `key`, `basePath`, `ops`, `locale`, `orgPrefix`. Custom clients use `orgPrefix: true` (base `/custom/<name>/v1/organizations/{orgId}`); the shipped `sfnextNotify` entry is a working example. ## Import rule Import types and clients from the barrel, not from the runtime package: ```typescript import { ApiError, type ShopperProducts } from '@/scapi'; // picks up overrides // import { ShopperProducts } from '@salesforce/storefront-next-runtime/scapi'; // bypasses overrides, lint warns ``` Only `src/scapi/**` and `src/lib/api-clients.server.ts` may import the runtime path directly. ## Use clients in loaders and actions ```typescript import { createApiClients } from '@/lib/api-clients.server'; export async function loader({ context }: LoaderFunctionArgs) { const clients = createApiClients(context); const { data: product } = await clients.shopperProducts.getProduct({ params: { path: { id: 'my-product-id' } }, }); const { data: rewards } = await clients.loyalty.getLoyaltyRewards(); // custom client return { product, rewardTier: product?.c_loyaltyTier, rewards }; } ``` - Calls return `{ data }` and **throw** `ApiError` on failure (wrap in `NormalizedApiError` from `@/lib/api/normalized-api-error` when you need a message/status). - `createApiClients` automatically injects `organizationId`, `siteId` and (when the client supports it) `locale`. Do not pass `siteId` yourself. - Auth comes from the shopper token in the auth middleware (`storefront-next:sfnext-authentication`); do not read tokens to call SCAPI manually. Get the shopper via `getAuth(context)` only when you need `customerId`. - Prefer the existing helpers in `src/lib/api/*.server.ts` (search, products, basket, wishlist, order) for standard APIs, and put your own custom-API calls in a new `src/lib/api/<thing>.server.ts`. - Calling from the browser: `useScapiFetcher(client, method, options)` goes through `/resource/api/client/...`, which only allows a short **allow-list** of operations (`src/lib/scapi/resource-policy.ts`), and `siteId`/`locale`/`organizationId` are server-owned. A new custom operation is not callable from the browser until you add it there; prefer a route loader/action. The `'helpers'` overload is deprecated. See `docs/README-PERFORMANCE.md` and `docs/README-REVALIDATION.md` for fetcher lifecycle rules. ## End-to-end: a new custom API 1. **Author the endpoint** (cartridge `rest-apis/<api-name>/` with `api.json`, `schema.yaml`, script) using `b2c:b2c-custom-api-development`. `api.json` maps `endpoint` to `schema` and `implementation`; auth is declared in `schema.yaml` (`ShopperToken` for storefront calls, with a `c_` scope under `security:`). The shipped `cartridges/app_storefrontnext_base/cartridge/rest-apis/sfnext-notify/` is a complete example. 2. **Deploy and activate**: `b2c code deploy <cartridge> --reload` (reload toggles activation so endpoints re-register; see `b2c-cli:b2c-code`). 3. **Confirm registration**: `b2c scapi custom status --tenant-id <id>` (filter with `--status not_registered`). Use `b2c-cli:b2c-scapi-custom` for 404s and `errorReason`. 4. **Allow the scope**: add the custom scope to the SLAS client used by the storefront (`b2c-cli:b2c-slas`). The shopper token must carry it, otherwise calls get 401/403. 5. **Register in the storefront**: `b2c sfnext scapi add custom <api-name> v1` (or `--schema` with a local copy). 6. **Call it** from a server loader/action as above; `import type` request/response types from `@/scapi`. 7. After schema changes repeat steps 2 and 5. ## Non-personalized caching Storefront Next can add `personalized=none` to eligible GET requests through one central policy. Overrides and custom clients are **left unclassified** until you review and approve their exact transports in the policy module. Do not loosen it to `() => true`. See `docs/README-SCAPI-NON-PERSONALIZED-RESPONSES.md` before approving a client. ## Pitfalls - Expecting `scapi add shopper-search ...` to be needed: standard clients already exist. - Importing from `@salesforce/storefront-next-runtime/scapi` and wondering why `c_*` is untyped. - Forgetting `--reload` after deploy, so the endpoint stays unregistered (404). - Passing `siteId` or `locale` in `params.query`: server-owned, stripped on the resource route and injected elsewhere. - Override key typos: the key must exactly match a built-in (`shopperProducts`, `shopperBasketsV2`, ...) or you create an unrelated custom client. - Custom client used from the browser fetcher without allow-listing it. Worked example of a shipped custom API: [references/WORKED-EXAMPLE.md](references/WORKED-EXAMPLE.md). ## Related Skills - `b2c:b2c-custom-api-development` - author the cartridge, api.json, schema.yaml, scripts - `b2c-cli:b2c-scapi-custom` - registration status and debugging 404s - `b2c-cli:b2c-scapi-schemas` - browse SCAPI schemas - `b2c-cli:b2c-slas` - add custom scopes to the SLAS client - `storefront-next:sfnext-data-fetching` - loaders, actions, caching - `storefront-next:sfnext-authentication` - `getAuth`, sessions - `storefront-next:sfnext-revalidation` - fetcher revalidation rules
عرض على GitHub