feat(ep-commerce): publish $ctx.productExtensions from product provider (ADR-0007)#350
Merged
Merged
Conversation
…er; relocate extension primitives to shared utils/types (ADR-0007)
Adds a flat, null-safe, slug-keyed product-extensions map (buildExtensionsMap; Proxy returns {} for absent slugs) published as $ctx.productExtensions by EPProductProvider, so designers and custom components bind to curated named fields instead of raw rawData chains. Relocates the pure extension primitives (format, Extension* types, mocks) from product-extensions/composable into shared utils/+types so product/ depends downward; all internal importers updated to the new paths. Decision recorded in ADR-0007 (iso-storefront). extensions-map.test.ts passes under root jest.
9d7548f to
78dd75d
Compare
This was referenced Jun 5, 2026
field123
added a commit
that referenced
this pull request
Jun 11, 2026
…ation (#372) * fix(ep-commerce): payment-integrity hardening for the composable checkout Server-authoritative integrity fixes in the checkout-session pipeline (#369), all test-first and housed in a new security regression suite (#325). - Free-vs-paid: settle a free order only on an authoritative meta.display_price total of 0. Removes the item-summing fallback that let a paid cart whose items didn't parse settle via the manual gateway with no charge; an absent total now fails closed to the paid path. - Order-fields allow-list: gate client customAttributes against a server-side allowedCustomAttributeKeys list (string[] | "*"), enforced at the updateSession boundary and again before the EP cart/order writes. Fail closed when unset; "*" is an explicit permissive opt-out. Stops a client forging or overwriting defined order-flow slugs (e.g. consent/audit fields) via session.customAttributes. - confirmOrder reconciliation: verify a real paymentID before calling; on a missing id or a failure, log at error level and mark the session needsReconciliation plus a reconciliationPending response flag instead of swallowing the failure. The order is already charged, so it still completes, but a charged-but-unreconciled order is now discoverable. - Server-authoritative requiresShipping: infer the requirement from the cart's product commodity_type (batched product lookup, run only when the client suppressed shipping); the client flag may only add a requirement, never suppress one a physical cart imposes. A physical cart can no longer ship to the billing address via requiresShipping:false. Fails open on a total lookup error (availability), closed on a partial resolution. The security suite also adds token-leak assertions across all checkout-session routes (including the order-custom-fields write and free-order branch) and a no-PII-logging assertion. Full elastic-path suite green (118 suites / 1882 tests). * fix(ep-commerce): repair package build after the #350 extension relocation - Drop duplicate FormatSpec imports from a non-existent ./format module in product-extensions (useResolvedField.tsx, resolve-field.ts) — stale leftovers from the ADR-0007 primitive relocation that broke the tsdx esm typecheck. - Sync build-server.mjs's hand-written server.d.ts re-export template with src/server.ts (it had drifted: missing createClientCredentialsTokenResolver plus several cart functions/types), so the server entry's runtime exports have matching type declarations.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Publishes the current product's extensions as a flat, null-safe, slug-keyed map on
$ctx.productExtensionsfromEPProductProvider, so designers and custom components bind to curated named fields — e.g.$ctx.productExtensions['products(iso-standard)'].reference— instead of raw$ctx.currentProduct.rawData.data.attributes.extensions[...]chains.Why
Companion to the field-display components (#333/#339): those insulate rendered fields; this insulates bindable values (component props,
hrefs) that a rendering component can't feed. It's the visual-builder "curated named data source" pattern — Plasmic's native equivalent is aDataProviderwhose fields are discoverable in the data picker.Changes
utils/extensions-map.ts—buildExtensionsMap(templates)flattens to{ slug: { key: value } }, keyed by the raw template slug (same value the field components'templateprop uses) and exposing raw values. AProxyreturns a frozen{}for absent slugs so a binding can never throw — the only missing-slug-safe path insideset-data-cond, which rejects?.. (Verified@plasmicapp/host'sDataProviderkeepsdataby reference, so the Proxy survives at runtime;ownKeyspasses through so picker discovery still works.)EPProductProviderpublishes$ctx.productExtensionsalongsidecurrentProduct, with a canvas mock-swap mirroringEPProductExtensionsProviderso design-time preview stays populated.product-extensions/composable/into shared lower layers soproduct/depends downward, not up:format.ts→utils/field-format.ts,Extension*types →types/extensions.ts, mocks →utils/extensions-mock.ts. All internal importers updated.Tests
utils/__tests__/extensions-map.test.ts— 5/5 passing (root jest): raw-slug keying, raw values, absent-slug{}, absent-fieldundefined, empty-templates.Notes