feat(pos): add TypeScript types for pos.app.ready.data background target#4123
feat(pos): add TypeScript types for pos.app.ready.data background target#4123vctrchu wants to merge 2 commits into2026-07-rcfrom
Conversation
🚨🚨🚨 Docs migration in progress 🚨🚨🚨We are actively migrating UI extension reference docs to MDX in the
During this migration, please be aware of the following:
Doc comments in Examples that previously lived in this repo are being moved to the What should I do?
Thanks for your patience while we complete the migration! 🙏 |
1ac2792 to
405dc2b
Compare
|
Warning This pull request is not mergeable via GitHub because a downstack PR is open. Once all requirements are satisfied, merge this PR as a stack on Graphite.
This stack of pull requests is managed by Graphite. Learn more about stacking. |
6528efa to
2d36a20
Compare
NathanJolly
left a comment
There was a problem hiding this comment.
This PR has the target definition and DataTargetApi, but it's missing two things that should ship together:
-
addEventListener / removeEventListener — needs to be part of
DataTargetApi(or the target's API surface). The generic types are defined in the TAG proposal (ui-api-design PR #1418), and the surface-specificPosEventMapwith concrete event types + payloads should be defined here. -
PosEventMap — the typed event map with
transaction_complete,cash_tracking_session_start,cash_tracking_session_completeand their payload interfaces. This is what makes addEventListener type-safe for POS.
Without these, extensions targeting pos.app.ready.data have no way to type-safely listen for events.
|
Added both. |
8ce7778 to
06eeda4
Compare
e2c600a to
e63759e
Compare
c9e53ce to
83610ef
Compare
|
/snapit |
83610ef to
3b55663
Compare
|
🫰✨ Thanks @vctrchu! Your snapshots have been published to npm. Test the snapshots by updating your "@shopify/ui-extensions": "0.0.0-snapshot-20260330221356",
"@shopify/ui-extensions-tester": "0.0.0-snapshot-20260330221356" |
93c4e1d to
6edab18
Compare
6edab18 to
5d0a28d
Compare
5d0a28d to
7ab45d5
Compare
58916be to
b72ad92
Compare
Introduces the new `pos.app.ready.data` data extension target (non-rendering, session-long background extension) along with its typed event surface: - `DataExtensionTargets` / `DataExtensionTarget` / `DataTargetApi<T>` - `ShopifyGlobal` with `addEventListener` / `removeEventListener` - `ShopifyEventMap` mapping 3 event names to Event subclasses: - transactioncomplete (TransactionCompleteEvent — Sale | Return | Exchange) - cashtrackingsessionstart (CashTrackingSessionStartEvent) - cashtrackingsessioncomplete (CashTrackingSessionCompleteEvent) - Mock factory for pos.app.ready.data in ui-extensions-tester Events live at the surface level (point-of-sale/events/ with events.ts barrel) since they are dispatched on the global `shopify` object and consumable by any target, not scoped to data-target extensions.
Mirrors #4299 for the new pos.app.ready.data target: - Intersect DataTargetApi<T> with ExtensionApi<T> so data extensions can read shopify.extension.apiVersion and shopify.extension.target. - Mark extensionPoint as @deprecated in favor of extension.target, matching the StandardApi change. - Populate extension: { apiVersion, target } in createDataTargetMock.
b72ad92 to
5e4a3ba
Compare
|
/snapit |
|
🫰✨ Thanks @vctrchu! Your snapshots have been published to npm. Test the snapshots by updating your "@shopify/ui-extensions": "0.0.0-snapshot-20260420225138",
"@shopify/ui-extensions-tester": "0.0.0-snapshot-20260420225138" |
js-goupil
left a comment
There was a problem hiding this comment.
Couple of tiny things that we should address before merging so we don't break the navigation listener
| /** | ||
| * The unique numeric identifier for the Shopify order created by this transaction. This ID links the POS transaction to the order record in Shopify's system and can be used for order lookups, tracking, and API operations. Returns `undefined` when order creation is pending. | ||
| */ | ||
| readonly orderId?: number; |
There was a problem hiding this comment.
Should this be Order { id: number } like customer?
| * their return values are ignored, and their errors are caught without | ||
| * affecting the host or other listeners. | ||
| */ | ||
| addEventListener<K extends keyof ShopifyEventMap>( |
There was a problem hiding this comment.
This might override the addEventListener that we create in navigation-api.ts. If anything, we should move 'currententrychange key into the ShopifyEventMap in events.ts

What
Add TypeScript types for the
pos.app.ready.datapersistent background extension target.New types
DataTargetApi<T>— API surface for non-rendering data targets. Includes non-UI APIs (cart, storage, session, locale, connectivity, device, product search); excludes UI-presenting APIs.ShopifyEventMap— Maps event names to their typedEventsubclasses (transactioncomplete,cashtrackingsessionstart,cashtrackingsessioncomplete).DataExtensionTargets— New target interface withpos.app.ready.dataas aRunnableExtension<DataTargetApi, undefined>.DataExtensionTarget— Type alias for data target keys.ShopifyGlobal— POSshopifyglobal type, augmented withaddEventListener/removeEventListenerkeyed onShopifyEventMap. Follows the samedeclare globalpattern Checkout uses.Event types
TransactionCompleteEvent— Discriminated union of three module-local variant interfaces (SaleCompleteEvent | ReturnCompleteEvent | ExchangeCompleteEvent), each extendingBaseTransactionCompleteEvent. All fields arereadonly. Narrow onevent.transactionType('Sale'|'Return'|'Exchange') to access per-type fields (lineItems,refundId,lineItemsAdded, etc.). Shared fields (orderId,grandTotal,customer,paymentMethods, …) are available without narrowing. The three variants are internal scaffolding — onlyTransactionCompleteEventis part of the public surface.BaseTransactionCompleteEvent— Internal shared base extendingEvent. Contains the 12 fields common to Sale/Return/Exchange (orderId, customer, grandTotal, taxTotal, paymentMethods, shippingLines, etc.).CashTrackingSessionStartEvent—Eventsubclass withid: numberandopeningTime: string(ISO 8601).CashTrackingSessionCompleteEvent— AddsclosingTime: string.Folder structure
Event types live at the surface-level
point-of-sale/events/(sibling toapi/andglobals.ts), not nested insideapi/data-target-api/. Host events are dispatched on the globalshopifyobject and consumable by any target, so they aren't scoped to a specific API. The layout mirrors the existingapi.ts+api/pattern:shopifyglobal augmentationPOS host events are received via
shopify.addEventListener()on the globalshopifyobject, consistent with TAG proposal Shopify/ui-api-design#1418.Why
POS apps need a persistent background extension that starts when POS loads and runs for the session lifetime. This replaces the existing fire-and-forget
.event.observetargets with a single long-lived target that receives events viashopify.addEventListener, aligning with the shape TAG approved in Shopify/ui-api-design#1418.Related PRs
eventListenerPlugin+eventDispatchFactory): Shopify/extensibility#1064Status
Draft until TAG approves Shopify/ui-api-design#1418. Types will publish with the 2026-07 quarterly release train.