From 1602f486fd369f83f857497531902ce0bd2410ec Mon Sep 17 00:00:00 2001 From: Henry Stelle Date: Wed, 5 Aug 2026 17:03:49 -0700 Subject: [PATCH 1/3] Add POS intercept API types Assisted-By: devx/f72cb0ba-11c1-4cc7-ab65-755169af9570 Add POS intercept name constant Assisted-By: devx/f72cb0ba-11c1-4cc7-ab65-755169af9570 Mark POS intercept types as private --- .changeset/pos-intercept-api.md | 5 + .../src/surfaces/point-of-sale/events.ts | 94 +++++++++++++++++++ .../src/surfaces/point-of-sale/globals.ts | 17 +++- 3 files changed, 115 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 2cb0150cda..bd4a1d628f 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 @@ -16,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`. + * + * @private + */ +export const POS_INTERCEPT_NAMES = { + BEFORE_CHECKOUT: 'beforecheckout', +} as const; + /** * Maps Shopify POS event names to their corresponding payload types. * @@ -36,6 +47,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`. + * + * @private + */ +export interface ShopifyInterceptMap { + [POS_INTERCEPT_NAMES.BEFORE_CHECKOUT]: BeforeCheckoutEvent; +} + +/** + * Dispatched when staff attempts to leave the active cart for checkout. + * + * @private + */ +export interface BeforeCheckoutEvent extends Event { + readonly type: typeof POS_INTERCEPT_NAMES.BEFORE_CHECKOUT; + /** The POS cart at the point checkout was requested. */ + readonly cart: Cart; +} + +/** @private */ +export type ShopifyInterceptor = ( + event: TEvent, +) => InterceptResult; + +/** + * The result an interceptor returns. An empty `operations` list allows the + * workflow; an `ERROR` validation blocks it. + * + * @private + */ +export interface InterceptResult { + operations: Operation[]; +} + +/** + * A single host operation produced by an interceptor. + * + * @private + */ +export interface Operation { + validationAdd?: ValidationAdd; +} + +/** @private */ +export type ValidationLevel = 'INFO' | 'WARNING' | 'ERROR'; + +/** + * Adds a validation to the workflow being intercepted. + * + * @private + */ +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. + * + * @private + */ +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..1dadafca5c 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,17 @@ 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. + * + * @private + */ + intercept( + type: K, + interceptor: ShopifyInterceptor, + ): () => void; } declare global { From 80b45ee45d76e1a9ae89a6355610635ebeefd6b7 Mon Sep 17 00:00:00 2001 From: Victor Chu Date: Thu, 6 Aug 2026 15:03:57 -0700 Subject: [PATCH 2/3] refactor: remove message, metafields, and INFO level from POS intercept validations Assisted-By: devx/9207e17f-e39b-4a11-8404-6b6307beb973 --- .../src/surfaces/point-of-sale/events.ts | 22 ++----------------- 1 file changed, 2 insertions(+), 20 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 bd4a1d628f..53e7648d5b 100644 --- a/packages/ui-extensions/src/surfaces/point-of-sale/events.ts +++ b/packages/ui-extensions/src/surfaces/point-of-sale/events.ts @@ -94,7 +94,7 @@ export interface Operation { } /** @private */ -export type ValidationLevel = 'INFO' | 'WARNING' | 'ERROR'; +export type ValidationLevel = 'WARNING' | 'ERROR'; /** * Adds a validation to the workflow being intercepted. @@ -102,32 +102,14 @@ export type ValidationLevel = 'INFO' | 'WARNING' | 'ERROR'; * @private */ export interface ValidationAdd { - /** `ERROR` blocks the workflow. `WARNING` and `INFO` do not. */ + /** `ERROR` blocks the workflow. `WARNING` does 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. - * - * @private - */ -export interface Metafield { - namespace: string; - key: string; - value: string; - type: string; } export type { From 69a7ae14c835740bb417638dd592d76c3698d945 Mon Sep 17 00:00:00 2001 From: Victor Chu Date: Thu, 6 Aug 2026 15:05:04 -0700 Subject: [PATCH 3/3] docs: remove default target note from POS intercept validation Assisted-By: devx/9207e17f-e39b-4a11-8404-6b6307beb973 --- packages/ui-extensions/src/surfaces/point-of-sale/events.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 53e7648d5b..85894cc601 100644 --- a/packages/ui-extensions/src/surfaces/point-of-sale/events.ts +++ b/packages/ui-extensions/src/surfaces/point-of-sale/events.ts @@ -108,7 +108,7 @@ export interface ValidationAdd { /** Stable identifier for this validation. */ handle: string; - /** JSON-path locator for where the validation applies. Defaults to `$.cart`. */ + /** JSON-path locator for where the validation applies. */ target?: string; }