From 7c09adc08a31df6332edd0c667aecf6effbcd341 Mon Sep 17 00:00:00 2001 From: Monorail CI check running in Buildkite Date: Mon, 22 Jun 2026 15:53:33 -0400 Subject: [PATCH 1/2] Add POS intercept API types Assisted-By: devx/f72cb0ba-11c1-4cc7-ab65-755169af9570 --- .changeset/pos-intercept-api.md | 5 ++ .../src/surfaces/point-of-sale/events.ts | 84 +++++++++++++++++++ .../src/surfaces/point-of-sale/globals.ts | 15 +++- 3 files changed, 103 insertions(+), 1 deletion(-) create mode 100644 .changeset/pos-intercept-api.md diff --git a/.changeset/pos-intercept-api.md b/.changeset/pos-intercept-api.md new file mode 100644 index 0000000000..4987223fc7 --- /dev/null +++ b/.changeset/pos-intercept-api.md @@ -0,0 +1,5 @@ +--- +'@shopify/ui-extensions': minor +--- + +Add `shopify.intercept()` types for POS blocking workflows. diff --git a/packages/ui-extensions/src/surfaces/point-of-sale/events.ts b/packages/ui-extensions/src/surfaces/point-of-sale/events.ts index f8100cb31a..de72375cea 100644 --- a/packages/ui-extensions/src/surfaces/point-of-sale/events.ts +++ b/packages/ui-extensions/src/surfaces/point-of-sale/events.ts @@ -3,6 +3,7 @@ import type { CashTrackingSessionStartEvent, CashTrackingSessionCompleteEvent, } from './events/cash-tracking-session-events'; +import type {Cart} from './types/cart'; /** * Canonical event-name constants for POS host events. Prefer these over string @@ -30,6 +31,89 @@ export interface ShopifyEventMap { [POS_EVENT_NAMES.CASH_TRACKING_SESSION_COMPLETE]: CashTrackingSessionCompleteEvent; } +/** + * Maps POS interceptable workflow names to their corresponding `Event` types. + * + * Used as the generic type parameter for `shopify.intercept`. + * + * @publicDocs + */ +export interface ShopifyInterceptMap { + beforecheckout: BeforeCheckoutEvent; +} + +/** + * Dispatched when staff attempts to leave the active cart for checkout. + * + * @publicDocs + */ +export interface BeforeCheckoutEvent extends Event { + readonly type: 'beforecheckout'; + /** The POS cart at the point checkout was requested. */ + readonly cart: Cart; +} + +/** @publicDocs */ +export type ShopifyInterceptor = ( + event: TEvent, +) => InterceptResult; + +/** + * The result an interceptor returns. An empty `operations` list allows the + * workflow; an `ERROR` validation blocks it. + * + * @publicDocs + */ +export interface InterceptResult { + operations: Operation[]; +} + +/** + * A single host operation produced by an interceptor. + * + * @publicDocs + */ +export interface Operation { + validationAdd?: ValidationAdd; +} + +/** @publicDocs */ +export type ValidationLevel = 'INFO' | 'WARNING' | 'ERROR'; + +/** + * Adds a validation to the workflow being intercepted. + * + * @publicDocs + */ +export interface ValidationAdd { + /** `ERROR` blocks the workflow. `WARNING` and `INFO` do not. */ + level: ValidationLevel; + + /** Stable identifier for this validation. */ + handle: string; + + /** Host-facing message for support, observability, or staff UX. */ + message: string; + + /** JSON-path locator for where the validation applies. Defaults to `$.cart`. */ + target?: string; + + /** Optional structured data for custom UX or order metadata. */ + metafields?: Metafield[]; +} + +/** + * Metafield input attached to a validation. + * + * @publicDocs + */ +export interface Metafield { + namespace: string; + key: string; + value: string; + type: string; +} + export type { TransactionCompleteEvent, CashTrackingSessionStartEvent, diff --git a/packages/ui-extensions/src/surfaces/point-of-sale/globals.ts b/packages/ui-extensions/src/surfaces/point-of-sale/globals.ts index 67533a92d7..bae46a34dc 100644 --- a/packages/ui-extensions/src/surfaces/point-of-sale/globals.ts +++ b/packages/ui-extensions/src/surfaces/point-of-sale/globals.ts @@ -1,5 +1,9 @@ import type {Navigation} from './api/navigation-api/navigation-api'; -import type {ShopifyEventMap} from './events'; +import type { + ShopifyEventMap, + ShopifyInterceptMap, + ShopifyInterceptor, +} from './events'; /** * The `shopify` global provides APIs that are available to all POS extensions @@ -36,6 +40,15 @@ export interface BackgroundShopifyGlobal extends ShopifyGlobal { type: K, listener: (event: ShopifyEventMap[K]) => void, ): void; + + /** + * Register an interceptor for a POS host workflow that can be blocked. + * Returns a function that unregisters the interceptor. + */ + intercept( + type: K, + interceptor: ShopifyInterceptor, + ): () => void; } declare global { From 22fdacd4ae9390d95b774a20542229845b20342e Mon Sep 17 00:00:00 2001 From: Monorail CI check running in Buildkite Date: Mon, 22 Jun 2026 16:11:27 -0400 Subject: [PATCH 2/2] Add POS intercept name constant Assisted-By: devx/f72cb0ba-11c1-4cc7-ab65-755169af9570 --- .../src/surfaces/point-of-sale/events.ts | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/packages/ui-extensions/src/surfaces/point-of-sale/events.ts b/packages/ui-extensions/src/surfaces/point-of-sale/events.ts index de72375cea..325d4b14ec 100644 --- a/packages/ui-extensions/src/surfaces/point-of-sale/events.ts +++ b/packages/ui-extensions/src/surfaces/point-of-sale/events.ts @@ -17,6 +17,16 @@ export const POS_EVENT_NAMES = { CASH_TRACKING_SESSION_COMPLETE: 'cashtrackingsessioncomplete', } as const; +/** + * Canonical workflow-name constants for POS host interceptions. Prefer these + * over string literals when calling `shopify.intercept`. + * + * @publicDocs + */ +export const POS_INTERCEPT_NAMES = { + BEFORE_CHECKOUT: 'beforecheckout', +} as const; + /** * Maps Shopify POS event names to their corresponding `Event` subclass types. * @@ -39,7 +49,7 @@ export interface ShopifyEventMap { * @publicDocs */ export interface ShopifyInterceptMap { - beforecheckout: BeforeCheckoutEvent; + [POS_INTERCEPT_NAMES.BEFORE_CHECKOUT]: BeforeCheckoutEvent; } /** @@ -48,7 +58,7 @@ export interface ShopifyInterceptMap { * @publicDocs */ export interface BeforeCheckoutEvent extends Event { - readonly type: 'beforecheckout'; + readonly type: typeof POS_INTERCEPT_NAMES.BEFORE_CHECKOUT; /** The POS cart at the point checkout was requested. */ readonly cart: Cart; }