Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
0e61431
feat: update page model and integration to support redirects (#777)
michnowak Mar 12, 2026
d4da911
chore(config): update renovate config to enable npm manager and weekl…
marcinkrasowski Mar 12, 2026
742ffbd
chore(config): update renovate config to disable OSV vulnerability al…
marcinkrasowski Mar 12, 2026
0a8b958
chore(deps): update commitlint monorepo to ^20.4.4 (#781)
renovate[bot] Mar 12, 2026
537413b
chore(deps): update dependency npm-check-updates to ^19.6.3 (#782)
renovate[bot] Mar 12, 2026
a1659cf
Fix/cli wizzard fixes (#774)
michnowak Mar 12, 2026
5d36519
feat/connecting cart and checkout API with frontend components (#754)
lukasz-hycom Mar 12, 2026
44136b0
feat(changeset): version packages (#780)
github-actions[bot] Mar 13, 2026
6b71db6
chore(deps): update npm to v11.11.1 (#786)
renovate[bot] Mar 13, 2026
b2a93ff
chore(deps): update storybook monorepo to ^10.2.17 (#787)
renovate[bot] Mar 13, 2026
83a3d13
chore(deps): update eslint monorepo to ^9.39.4 (#784)
renovate[bot] Mar 13, 2026
2b9533a
fix(deps): update dependency @easyops-cn/docusaurus-search-local to ^…
renovate[bot] Mar 13, 2026
e5addab
chore(deps): update dependency postcss to ^8.5.8 (#783)
renovate[bot] Mar 13, 2026
9f72807
fix(deps): update dependency @contentful/live-preview to ^4.9.9 (#789)
renovate[bot] Mar 13, 2026
98b2e68
chore(deps): update storybook monorepo to ^10.2.18 (#793)
renovate[bot] Mar 13, 2026
fa91166
fix(deps): update dependency @medusajs/js-sdk to ^2.13.3 (#796)
renovate[bot] Mar 13, 2026
c1a5460
chore(deps): update dependency eslint to ^9.39.4 (#795)
renovate[bot] Mar 13, 2026
d05b09b
fix(deps): update dependency flatted to ^3.4.0 [security] (#803)
renovate[bot] Mar 16, 2026
daf592e
fix(deps): update dependency axios to ^1.13.6 (#801)
renovate[bot] Mar 16, 2026
a2d9ea4
feat: CLI UX improvements - branding, docs links & starter card updat…
michnowak Mar 16, 2026
028ce47
fix(deps): update dependency @medusajs/types to ^2.13.3 (#799)
renovate[bot] Mar 16, 2026
fa60ec9
chore(deps): update storybook monorepo to ^10.2.19 (#798)
renovate[bot] Mar 16, 2026
5334ba4
chore(deps): update dependency msw to ^2.12.11 (#805)
renovate[bot] Mar 16, 2026
3c0129d
fix(deps): update dependency @medusajs/js-sdk to ^2.13.4 (#807)
renovate[bot] Mar 16, 2026
0300d8e
fix(deps): update dependency @contentful/live-preview to ^4.9.10 (#806)
renovate[bot] Mar 16, 2026
6b7e6da
fix(deps): update dependency dayjs to ^1.11.20 (#809)
renovate[bot] Mar 16, 2026
375cd90
feature/handling cart items addition (#797)
lukasz-hycom Mar 16, 2026
555fc32
feat(changeset): version packages (#794)
github-actions[bot] Mar 16, 2026
924f413
fix(deps): update dependency algoliasearch to ^5.49.2 (#800)
renovate[bot] Mar 17, 2026
dd58165
fix(deps): update dependency @medusajs/types to ^2.13.4 (#808)
renovate[bot] Mar 17, 2026
feb0a8c
fix(deps): update dependency flatted to ^3.4.1 (#810)
renovate[bot] Mar 17, 2026
8c57c81
fix(deps): update dependency fs-extra to ^11.3.4 (#811)
renovate[bot] Mar 17, 2026
338cb01
Fix/quick wins followup (#757)
tomaszpacior Mar 17, 2026
fadbc63
768 feature create common block prop types (#772)
tomaszpacior Mar 17, 2026
44b3482
feat(changeset): version packages (#817)
github-actions[bot] Mar 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 2 additions & 0 deletions .prettierrc.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ const config = {
...apiConfig,
...webConfig,
...uiConfig,
// Required for .tsx files - parser was misinterpreting JSX as regex
importOrderParserPlugins: ['typescript', 'jsx', 'decorators-legacy'],
};

export default config;
9 changes: 8 additions & 1 deletion .storybook/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,13 @@ const config: StorybookConfig = {
'../packages/ui/**/*.stories.@(js|jsx|mjs|ts|tsx)',
],
staticDirs: ['./public'],
addons: ['@storybook/addon-docs', '@storybook/addon-a11y', '@storybook/addon-themes', '@storybook/addon-vitest'],
addons: [
'@storybook/addon-docs',
'@storybook/addon-a11y',
'@storybook/addon-themes',
'@storybook/addon-vitest',
'msw-storybook-addon',
],
framework: {
name: '@storybook/nextjs-vite',
options: {},
Expand Down Expand Up @@ -73,6 +79,7 @@ const config: StorybookConfig = {
'@o2s/configs.integrations/live-preview': path.resolve(__dirname, './mocks/live-preview.mock.ts'),
'@o2s/framework/sdk': path.resolve(__dirname, '../packages/framework/src/sdk.ts'),
'@o2s/framework/modules': path.resolve(__dirname, '../packages/framework/src/index.ts'),
'@o2s/utils.api-harmonization': path.resolve(__dirname, './mocks/utils.api-harmonization.mock.ts'),
},
},
ssr: {
Expand Down
219 changes: 219 additions & 0 deletions .storybook/mocks/data/cart-data.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,219 @@
/**
* Shared mock cart and checkout data for Storybook.
* Used by cart and checkout block SDK mocks.
*/

const MOCK_CART = {
id: 'storybook-cart-1',
customerId: 'cust-001',
createdAt: new Date().toISOString(),
updatedAt: new Date().toISOString(),
currency: 'EUR' as const,
regionId: 'reg-1',
items: {
data: [
{
id: 'item-1',
sku: 'SKU-001',
quantity: 2,
price: { value: 49.99, currency: 'EUR' as const },
subtotal: { value: 99.98, currency: 'EUR' as const },
discountTotal: { value: 0, currency: 'EUR' as const },
total: { value: 99.98, currency: 'EUR' as const },
unit: 'PCS' as const,
currency: 'EUR' as const,
product: {
id: 'prod-1',
sku: 'SKU-001',
name: 'Wireless Noise-Cancelling Headphones',
description: 'Premium over-ear headphones with active noise cancellation and 30h battery life',
shortDescription: 'Over-ear ANC headphones',
image: {
url: 'https://raw.githubusercontent.com/o2sdev/openselfservice/refs/heads/main/packages/integrations/mocked/public/images/prd-004_1.jpg',
width: 800,
height: 800,
alt: 'Wireless Noise-Cancelling Headphones',
},
price: { value: 49.99, currency: 'EUR' as const },
link: '/products/sample',
type: 'PHYSICAL' as const,
category: 'General',
tags: [],
},
},
{
id: 'item-2',
sku: 'SKU-002',
quantity: 1,
price: { value: 105, currency: 'EUR' as const },
subtotal: { value: 105, currency: 'EUR' as const },
discountTotal: { value: 0, currency: 'EUR' as const },
total: { value: 105, currency: 'EUR' as const },
unit: 'PCS' as const,
currency: 'EUR' as const,
product: {
id: 'prod-2',
sku: 'SKU-002',
name: 'USB-C Charging Cable (2m)',
description: 'Braided USB-C to USB-C fast charging cable, 2 meters',
shortDescription: 'USB-C charging cable',
image: {
url: 'https://raw.githubusercontent.com/o2sdev/openselfservice/refs/heads/main/packages/integrations/mocked/public/images/prd-005_1.jpg',
width: 800,
height: 800,
alt: 'USB-C Charging Cable',
},
price: { value: 105, currency: 'EUR' as const },
link: '/products/another',
type: 'PHYSICAL' as const,
category: 'General',
tags: [],
},
},
],
total: 2,
},
subtotal: { value: 204.98, currency: 'EUR' as const },
discountTotal: { value: 0, currency: 'EUR' as const },
taxTotal: { value: 47.14, currency: 'EUR' as const },
shippingTotal: { value: 0, currency: 'EUR' as const },
total: { value: 252.12, currency: 'EUR' as const },
billingAddress: {
firstName: 'John',
lastName: 'Doe',
companyName: 'ACME Inc.',
taxId: '1234567890',
country: 'PL',
streetName: 'Main Street',
streetNumber: '123',
city: 'Warsaw',
postalCode: '00-001',
email: 'john@example.com',
phone: '+48 123 456 789',
},
shippingAddress: {
firstName: 'John',
lastName: 'Doe',
country: 'PL',
streetName: 'Main Street',
streetNumber: '123',
city: 'Warsaw',
postalCode: '00-001',
phone: '+48 123 456 789',
},
shippingMethod: {
id: 'standard',
name: 'Standard Shipping',
description: '3-5 business days',
total: { value: 0, currency: 'EUR' as const },
subtotal: { value: 0, currency: 'EUR' as const },
},
paymentMethod: {
id: 'card',
name: 'Credit Card',
description: 'Pay with Visa, Mastercard',
},
promotions: [
{
id: 'promo-1',
code: 'SAVE10',
name: '10% Off',
type: 'PERCENTAGE' as const,
value: '10',
},
],
notes: '',
email: 'john@example.com',
};

/** Empty cart for EmptyCart story variant - use cartId "storybook-cart-empty" */
const MOCK_EMPTY_CART = {
...MOCK_CART,
id: 'storybook-cart-empty',
items: {
data: [],
total: 0,
},
subtotal: { value: 0, currency: 'EUR' as const },
discountTotal: { value: 0, currency: 'EUR' as const },
taxTotal: { value: 0, currency: 'EUR' as const },
shippingTotal: { value: 0, currency: 'EUR' as const },
total: { value: 0, currency: 'EUR' as const },
billingAddress: undefined,
shippingAddress: undefined,
shippingMethod: undefined,
paymentMethod: undefined,
promotions: undefined,
};

const MOCK_SHIPPING_OPTIONS = {
data: [
{
id: 'standard',
name: 'Standard Shipping',
description: '3-5 business days',
total: { value: 0, currency: 'EUR' as const },
subtotal: { value: 0, currency: 'EUR' as const },
},
{
id: 'express',
name: 'Express Shipping',
description: '1-2 business days',
total: { value: 15, currency: 'EUR' as const },
subtotal: { value: 15, currency: 'EUR' as const },
},
],
total: 2,
};

const MOCK_PAYMENT_PROVIDERS = {
data: [
{
id: 'card',
name: 'Credit Card',
description: 'Pay with Visa, Mastercard',
},
{
id: 'blik',
name: 'BLIK',
description: 'Instant mobile payment',
},
],
};

const MOCK_CHECKOUT_SUMMARY = {
cart: MOCK_CART,
shippingAddress: MOCK_CART.shippingAddress,
billingAddress: MOCK_CART.billingAddress,
shippingMethod: MOCK_CART.shippingMethod,
paymentMethod: MOCK_CART.paymentMethod,
totals: {
subtotal: MOCK_CART.subtotal,
shipping: MOCK_CART.shippingTotal ?? { value: 0, currency: 'EUR' as const },
tax: MOCK_CART.taxTotal ?? { value: 0, currency: 'EUR' as const },
discount: MOCK_CART.discountTotal ?? { value: 0, currency: 'EUR' as const },
total: MOCK_CART.total,
},
notes: MOCK_CART.notes,
email: MOCK_CART.email,
};

const MOCK_PLACE_ORDER_RESPONSE = {
order: {
id: 'ord-storybook-1',
total: MOCK_CART.total,
currency: 'EUR',
status: 'PENDING',
paymentStatus: 'PENDING',
},
paymentRedirectUrl: undefined,
};

export {
MOCK_CART,
MOCK_EMPTY_CART,
MOCK_SHIPPING_OPTIONS,
MOCK_PAYMENT_PROVIDERS,
MOCK_CHECKOUT_SUMMARY,
MOCK_PLACE_ORDER_RESPONSE,
};
52 changes: 52 additions & 0 deletions .storybook/mocks/handlers/cart-handlers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/**
* MSW handlers for cart and checkout API endpoints.
* Used by cart and checkout block stories.
* Path patterns match /api/carts/* and /api/checkout/* (NEXT_PUBLIC_API_URL base).
*/
import { HttpResponse, http } from 'msw';

import {
MOCK_CART,
MOCK_CHECKOUT_SUMMARY,
MOCK_EMPTY_CART,
MOCK_PAYMENT_PROVIDERS,
MOCK_PLACE_ORDER_RESPONSE,
MOCK_SHIPPING_OPTIONS,
} from '../data/cart-data';

/** Returns full cart for Default stories, empty cart for EmptyCart (cartId contains 'empty') */
const getCartResponse = (url: string) => {
const cartIdMatch = url.match(/\/carts\/([^/]+)/);
const cartId = cartIdMatch?.[1] ?? '';
return cartId.includes('empty') ? MOCK_EMPTY_CART : MOCK_CART;
};

// Match /api/carts/:id (GET), /api/carts/:id/items/:itemId (PATCH/DELETE), /api/carts/:id/promotions (POST/DELETE)
const CART_PATH = /\/api\/carts\/[^/]+/;
const CHECKOUT_SUMMARY_PATH = /\/api\/checkout\/[^/]+\/summary/;
const CHECKOUT_PLACE_ORDER_PATH = /\/api\/checkout\/[^/]+\/place-order/;
const CHECKOUT_SHIPPING_OPTIONS_PATH = /\/api\/checkout\/[^/]+\/shipping-options/;
const CHECKOUT_ADDRESSES_PATH = /\/api\/checkout\/[^/]+\/addresses/;
const CHECKOUT_SHIPPING_METHOD_PATH = /\/api\/checkout\/[^/]+\/shipping-method/;
const CHECKOUT_PAYMENT_PATH = /\/api\/checkout\/[^/]+\/payment/;
const PAYMENTS_PROVIDERS_PATH = /\/api\/payments\/providers/;

export const cartHandlers = [
http.get(CART_PATH, ({ request }) => HttpResponse.json(getCartResponse(request.url))),
http.patch(CART_PATH, ({ request }) => HttpResponse.json(getCartResponse(request.url))),
http.delete(CART_PATH, ({ request }) => HttpResponse.json(getCartResponse(request.url))),
http.post(CART_PATH, ({ request }) => HttpResponse.json(getCartResponse(request.url))),
];

export const checkoutHandlers = [
http.get(CHECKOUT_SUMMARY_PATH, () => HttpResponse.json(MOCK_CHECKOUT_SUMMARY)),
http.post(CHECKOUT_PLACE_ORDER_PATH, () => HttpResponse.json(MOCK_PLACE_ORDER_RESPONSE)),
http.get(CHECKOUT_SHIPPING_OPTIONS_PATH, () => HttpResponse.json(MOCK_SHIPPING_OPTIONS)),
http.post(CHECKOUT_ADDRESSES_PATH, ({ request }) => HttpResponse.json(getCartResponse(request.url))),
http.post(CHECKOUT_SHIPPING_METHOD_PATH, ({ request }) => HttpResponse.json(getCartResponse(request.url))),
http.post(CHECKOUT_PAYMENT_PATH, ({ request }) => HttpResponse.json(getCartResponse(request.url))),
];

export const paymentsHandlers = [http.get(PAYMENTS_PROVIDERS_PATH, () => HttpResponse.json(MOCK_PAYMENT_PROVIDERS))];

export const cartAndCheckoutHandlers = [...cartHandlers, ...checkoutHandlers, ...paymentsHandlers];
23 changes: 23 additions & 0 deletions .storybook/mocks/utils.api-harmonization.mock.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Browser-safe mock for @o2s/utils.api-harmonization.
* Exports only Models (Block, Headers) - avoids jsonwebtoken which uses Node.js util.inherits.
* The full package includes Utils.Auth that imports jsonwebtoken, causing "util.inherits is not a function" in Storybook.
*/

export class Block {
id!: string;
}

export class AppHeaders {
'x-locale'!: string;
'x-client-timezone'?: string;
'x-currency'?: string;
'authorization'?: string;
}

export const Models = {
Block: { Block },
Headers: { AppHeaders },
};

export const Utils = {} as Record<string, unknown>;
Loading
Loading