@open-mercato/checkout 0.6.1-develop.3054.g0367114684 → 0.6.1-develop.3060.d6cca7ade1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -97,7 +97,10 @@ async function createTemplateFixture(request, token, input) {
97
97
  data: input
98
98
  });
99
99
  const body = await readJsonSafe(response);
100
- expect(response.ok(), `Failed to create template: ${response.status()}`).toBeTruthy();
100
+ expect(
101
+ response.ok(),
102
+ `Failed to create template: ${response.status()} ${JSON.stringify(body)}`
103
+ ).toBeTruthy();
101
104
  expect(typeof body?.id === "string" && body.id.length > 0, "Template id is required").toBeTruthy();
102
105
  return body.id;
103
106
  }
@@ -107,7 +110,10 @@ async function createLinkFixture(request, token, input) {
107
110
  data: input
108
111
  });
109
112
  const body = await readJsonSafe(response);
110
- expect(response.ok(), `Failed to create link: ${response.status()}`).toBeTruthy();
113
+ expect(
114
+ response.ok(),
115
+ `Failed to create link: ${response.status()} ${JSON.stringify(body)}`
116
+ ).toBeTruthy();
111
117
  expect(typeof body?.id === "string" && body.id.length > 0, "Link id is required").toBeTruthy();
112
118
  expect(typeof body?.slug === "string" && body.slug.length > 0, "Link slug is required").toBeTruthy();
113
119
  return { id: body.id, slug: body.slug };
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/checkout/__integration__/helpers/fixtures.ts"],
4
- "sourcesContent": ["import { createHmac } from 'node:crypto'\nimport { expect, type APIRequestContext, type APIResponse, type Page } from '@playwright/test'\nimport { apiRequest } from '@open-mercato/core/modules/core/__integration__/helpers/api'\nimport {\n readJsonSafe,\n} from '@open-mercato/core/modules/core/__integration__/helpers/generalFixtures'\nimport type { PublicSubmitInput } from '../../data/validators'\n\nconst MOCK_GATEWAY_DEV_WEBHOOK_SECRET = 'open-mercato-mock-dev-webhook-secret'\nconst MOCK_GATEWAY_SIGNATURE_HEADER = 'x-mock-signature'\n\ntype JsonRecord = Record<string, unknown>\n\nlet forwardedIpSequence = Math.floor(Math.random() * 10_000)\n\nexport type CheckoutTemplateInput = {\n name: string\n title?: string | null\n subtitle?: string | null\n description?: string | null\n pricingMode: 'fixed' | 'custom_amount' | 'price_list'\n fixedPriceAmount?: number | null\n fixedPriceCurrencyCode?: string | null\n fixedPriceIncludesTax?: boolean\n fixedPriceOriginalAmount?: number | null\n customAmountMin?: number | null\n customAmountMax?: number | null\n customAmountCurrencyCode?: string | null\n priceListItems?: Array<{\n id: string\n description: string\n amount: number\n currencyCode: string\n }> | null\n gatewayProviderKey: string\n gatewaySettings?: Record<string, unknown>\n customFieldsetCode?: string | null\n collectCustomerDetails?: boolean\n legalDocuments?: {\n terms?: { title: string; markdown: string; required?: boolean }\n privacyPolicy?: { title: string; markdown: string; required?: boolean }\n }\n displayCustomFieldsOnPage?: boolean\n password?: string | null\n maxCompletions?: number | null\n status?: 'draft' | 'active' | 'inactive'\n customFields?: Record<string, unknown>\n}\n\nexport type CheckoutLinkInput = CheckoutTemplateInput & {\n templateId?: string | null\n slug?: string | null\n}\n\nexport type CheckoutLinkRecord = {\n id: string\n slug: string\n name?: string\n title?: string | null\n subtitle?: string | null\n status?: string\n templateId?: string | null\n completionCount?: number\n activeReservationCount?: number\n fixedPriceAmount?: number | null\n displayCustomFieldsOnPage?: boolean\n publicCustomFields?: Array<{ key?: string; label?: string; value?: unknown }>\n customerFieldsSchema?: Array<{ key: string; required?: boolean }>\n requiresPassword?: boolean\n available?: boolean\n remainingUses?: number | null\n gatewayProviderKey?: string | null\n customFields?: Record<string, unknown>\n}\n\nexport type CheckoutTransactionRecord = {\n id: string\n linkId?: string\n status: string\n paymentStatus?: string | null\n gatewayTransactionId?: string | null\n email?: string | null\n firstName?: string | null\n lastName?: string | null\n phone?: string | null\n acceptedLegalConsents?: Record<string, unknown> | null\n customerData?: Record<string, unknown> | null\n}\n\nexport type ExampleCapturedEvent = {\n event: string\n payload: Record<string, unknown>\n capturedAt: string\n}\n\nfunction uniqueLabel(prefix: string): string {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\n}\n\nfunction createUniqueForwardedIp(): string {\n forwardedIpSequence += 1\n const thirdOctet = Math.floor(forwardedIpSequence / 250) % 250 + 1\n const fourthOctet = forwardedIpSequence % 250 + 1\n return `198.51.${thirdOctet}.${fourthOctet}`\n}\n\nexport function createCheckoutClientHeaders(overrides: Record<string, string> = {}): Record<string, string> {\n if (overrides['x-forwarded-for'] || overrides['x-real-ip']) {\n return overrides\n }\n return {\n 'x-forwarded-for': createUniqueForwardedIp(),\n ...overrides,\n }\n}\n\nexport function createFixedTemplateInput(overrides: Partial<CheckoutLinkInput> = {}): CheckoutLinkInput {\n const label = uniqueLabel('checkout-fixed')\n return {\n name: `QA ${label}`,\n title: `QA ${label}`,\n subtitle: 'QA checkout fixture',\n description: 'QA checkout fixture description',\n pricingMode: 'fixed',\n fixedPriceAmount: 49.99,\n fixedPriceCurrencyCode: 'USD',\n fixedPriceIncludesTax: true,\n fixedPriceOriginalAmount: 69.99,\n gatewayProviderKey: 'mock',\n status: 'draft',\n collectCustomerDetails: true,\n displayCustomFieldsOnPage: false,\n ...overrides,\n }\n}\n\nexport function createCustomAmountTemplateInput(overrides: Partial<CheckoutLinkInput> = {}): CheckoutLinkInput {\n const label = uniqueLabel('checkout-custom')\n return {\n name: `QA ${label}`,\n title: `QA ${label}`,\n subtitle: 'QA custom amount fixture',\n description: 'QA custom amount description',\n pricingMode: 'custom_amount',\n customAmountMin: 10,\n customAmountMax: 100,\n customAmountCurrencyCode: 'USD',\n gatewayProviderKey: 'mock',\n status: 'active',\n collectCustomerDetails: true,\n displayCustomFieldsOnPage: false,\n ...overrides,\n }\n}\n\nexport function createPriceListTemplateInput(overrides: Partial<CheckoutLinkInput> = {}): CheckoutLinkInput {\n const label = uniqueLabel('checkout-price-list')\n return {\n name: `QA ${label}`,\n title: `QA ${label}`,\n subtitle: 'QA price list fixture',\n description: 'QA price list description',\n pricingMode: 'price_list',\n priceListItems: [\n { id: 'basic', description: 'Basic', amount: 19.99, currencyCode: 'USD' },\n { id: 'plus', description: 'Plus', amount: 49.99, currencyCode: 'USD' },\n ],\n gatewayProviderKey: 'mock',\n status: 'active',\n collectCustomerDetails: true,\n displayCustomFieldsOnPage: false,\n ...overrides,\n }\n}\n\nexport function createCustomerData(overrides: Record<string, unknown> = {}): Record<string, unknown> {\n const label = uniqueLabel('customer')\n return {\n firstName: 'Quinn',\n lastName: 'Checkout',\n email: `${label}@example.test`,\n phone: '+15550001111',\n ...overrides,\n }\n}\n\nexport async function createTemplateFixture(\n request: APIRequestContext,\n token: string,\n input: CheckoutTemplateInput,\n): Promise<string> {\n const response = await apiRequest(request, 'POST', '/api/checkout/templates', {\n token,\n data: input,\n })\n const body = await readJsonSafe<{ id?: string }>(response)\n expect(response.ok(), `Failed to create template: ${response.status()}`).toBeTruthy()\n expect(typeof body?.id === 'string' && body.id.length > 0, 'Template id is required').toBeTruthy()\n return body!.id!\n}\n\nexport async function createLinkFixture(\n request: APIRequestContext,\n token: string,\n input: CheckoutLinkInput,\n): Promise<{ id: string; slug: string }> {\n const response = await apiRequest(request, 'POST', '/api/checkout/links', {\n token,\n data: input,\n })\n const body = await readJsonSafe<{ id?: string; slug?: string }>(response)\n expect(response.ok(), `Failed to create link: ${response.status()}`).toBeTruthy()\n expect(typeof body?.id === 'string' && body.id.length > 0, 'Link id is required').toBeTruthy()\n expect(typeof body?.slug === 'string' && body.slug.length > 0, 'Link slug is required').toBeTruthy()\n return { id: body!.id!, slug: body!.slug! }\n}\n\nexport async function readTemplate(\n request: APIRequestContext,\n token: string,\n templateId: string,\n): Promise<JsonRecord> {\n const response = await apiRequest(request, 'GET', `/api/checkout/templates/${encodeURIComponent(templateId)}`, { token })\n expect(response.ok(), `Failed to read template ${templateId}: ${response.status()}`).toBeTruthy()\n return (await readJsonSafe<JsonRecord>(response)) ?? {}\n}\n\nexport async function readLink(\n request: APIRequestContext,\n token: string,\n linkId: string,\n): Promise<CheckoutLinkRecord> {\n const response = await apiRequest(request, 'GET', `/api/checkout/links/${encodeURIComponent(linkId)}`, { token })\n expect(response.ok(), `Failed to read link ${linkId}: ${response.status()}`).toBeTruthy()\n return ((await readJsonSafe<CheckoutLinkRecord>(response)) ?? {}) as CheckoutLinkRecord\n}\n\nexport async function updateTemplate(\n request: APIRequestContext,\n token: string,\n templateId: string,\n data: Record<string, unknown>,\n): Promise<APIResponse> {\n return apiRequest(request, 'PUT', `/api/checkout/templates/${encodeURIComponent(templateId)}`, {\n token,\n data,\n })\n}\n\nexport async function updateLink(\n request: APIRequestContext,\n token: string,\n linkId: string,\n data: Record<string, unknown>,\n): Promise<APIResponse> {\n return apiRequest(request, 'PUT', `/api/checkout/links/${encodeURIComponent(linkId)}`, {\n token,\n data,\n })\n}\n\nexport async function deleteTemplate(\n request: APIRequestContext,\n token: string,\n templateId: string,\n): Promise<APIResponse> {\n return apiRequest(request, 'DELETE', `/api/checkout/templates/${encodeURIComponent(templateId)}`, { token })\n}\n\nexport async function deleteLink(\n request: APIRequestContext,\n token: string,\n linkId: string,\n): Promise<APIResponse> {\n return apiRequest(request, 'DELETE', `/api/checkout/links/${encodeURIComponent(linkId)}`, { token })\n}\n\nexport async function listTemplates(\n request: APIRequestContext,\n token: string,\n query = '',\n): Promise<{ items: JsonRecord[]; total: number }> {\n const response = await apiRequest(request, 'GET', `/api/checkout/templates${query ? `?${query}` : ''}`, { token })\n expect(response.ok(), `Failed to list templates: ${response.status()}`).toBeTruthy()\n return ((await readJsonSafe<{ items?: JsonRecord[]; total?: number }>(response)) ?? {\n items: [],\n total: 0,\n }) as { items: JsonRecord[]; total: number }\n}\n\nexport async function listLinks(\n request: APIRequestContext,\n token: string,\n query = '',\n): Promise<{ items: JsonRecord[]; total: number }> {\n const response = await apiRequest(request, 'GET', `/api/checkout/links${query ? `?${query}` : ''}`, { token })\n expect(response.ok(), `Failed to list links: ${response.status()}`).toBeTruthy()\n return ((await readJsonSafe<{ items?: JsonRecord[]; total?: number }>(response)) ?? {\n items: [],\n total: 0,\n }) as { items: JsonRecord[]; total: number }\n}\n\nexport async function readPublicPayLink(\n request: APIRequestContext,\n slug: string,\n options?: { headers?: Record<string, string>; preview?: boolean },\n): Promise<APIResponse> {\n const query = options?.preview ? '?preview=true' : ''\n return request.fetch(`${process.env.BASE_URL || 'http://localhost:3000'}/api/checkout/pay/${encodeURIComponent(slug)}${query}`, {\n method: 'GET',\n headers: createCheckoutClientHeaders(options?.headers),\n })\n}\n\nexport async function verifyPayLinkPassword(\n request: APIRequestContext,\n slug: string,\n password: string,\n): Promise<APIResponse> {\n return request.fetch(`${process.env.BASE_URL || 'http://localhost:3000'}/api/checkout/pay/${encodeURIComponent(slug)}/verify-password`, {\n method: 'POST',\n headers: createCheckoutClientHeaders({ 'Content-Type': 'application/json' }),\n data: { password },\n })\n}\n\nexport async function submitPayLink(\n request: APIRequestContext,\n slug: string,\n input: PublicSubmitInput,\n options?: { idempotencyKey?: string; headers?: Record<string, string> },\n): Promise<APIResponse> {\n return request.fetch(`${process.env.BASE_URL || 'http://localhost:3000'}/api/checkout/pay/${encodeURIComponent(slug)}/submit`, {\n method: 'POST',\n headers: createCheckoutClientHeaders({\n 'Content-Type': 'application/json',\n 'Idempotency-Key': options?.idempotencyKey ?? uniqueLabel('idempotency'),\n ...(options?.headers ?? {}),\n }),\n data: input,\n })\n}\n\nexport async function readCheckoutTransaction(\n request: APIRequestContext,\n token: string,\n transactionId: string,\n): Promise<CheckoutTransactionRecord> {\n const response = await apiRequest(request, 'GET', `/api/checkout/transactions/${encodeURIComponent(transactionId)}`, { token })\n expect(response.ok(), `Failed to read transaction ${transactionId}: ${response.status()}`).toBeTruthy()\n const body = (await readJsonSafe<{ transaction?: CheckoutTransactionRecord }>(response)) ?? {}\n return (body.transaction ?? {}) as CheckoutTransactionRecord\n}\n\nexport async function listCheckoutTransactions(\n request: APIRequestContext,\n token: string,\n query = '',\n): Promise<{ items: CheckoutTransactionRecord[]; total: number; canViewPii?: boolean }> {\n const response = await apiRequest(request, 'GET', `/api/checkout/transactions${query ? `?${query}` : ''}`, { token })\n expect(response.ok(), `Failed to list checkout transactions: ${response.status()}`).toBeTruthy()\n return ((await readJsonSafe<{ items?: CheckoutTransactionRecord[]; total?: number; canViewPii?: boolean }>(response)) ?? {\n items: [],\n total: 0,\n }) as { items: CheckoutTransactionRecord[]; total: number; canViewPii?: boolean }\n}\n\nexport async function readCheckoutStatus(\n request: APIRequestContext,\n slug: string,\n transactionId: string,\n options?: { headers?: Record<string, string> },\n): Promise<APIResponse> {\n return request.fetch(\n `${process.env.BASE_URL || 'http://localhost:3000'}/api/checkout/pay/${encodeURIComponent(slug)}/status/${encodeURIComponent(transactionId)}`,\n {\n method: 'GET',\n headers: createCheckoutClientHeaders(options?.headers),\n },\n )\n}\n\nexport async function waitForCheckoutStatus(\n request: APIRequestContext,\n token: string,\n transactionId: string,\n expectedStatus: string,\n): Promise<CheckoutTransactionRecord> {\n for (let attempt = 0; attempt < 20; attempt += 1) {\n const transaction = await readCheckoutTransaction(request, token, transactionId)\n if (transaction.status === expectedStatus) return transaction\n await new Promise((resolve) => setTimeout(resolve, 150))\n }\n return readCheckoutTransaction(request, token, transactionId)\n}\n\nexport async function findGatewayTransactionIdForCheckout(\n request: APIRequestContext,\n token: string,\n checkoutTransactionId: string,\n): Promise<string> {\n const response = await apiRequest(request, 'GET', '/api/payment_gateways/transactions?page=1&pageSize=100', { token })\n expect(response.ok(), `Failed to list gateway transactions: ${response.status()}`).toBeTruthy()\n const body = (await readJsonSafe<{ items?: Array<{ id: string; paymentId: string }> }>(response)) ?? {}\n const match = body.items?.find((item) => item.paymentId === checkoutTransactionId)\n expect(match, `Gateway transaction for checkout ${checkoutTransactionId} was not found`).toBeTruthy()\n return match!.id\n}\n\nexport async function readGatewayTransaction(\n request: APIRequestContext,\n token: string,\n gatewayTransactionId: string,\n): Promise<{\n id: string\n providerSessionId: string | null\n unifiedStatus: string\n}> {\n const response = await apiRequest(request, 'GET', `/api/payment_gateways/transactions/${encodeURIComponent(gatewayTransactionId)}`, { token })\n expect(response.ok(), `Failed to read gateway transaction ${gatewayTransactionId}: ${response.status()}`).toBeTruthy()\n const body = (await readJsonSafe<{ transaction?: { id: string; providerSessionId?: string | null; unifiedStatus?: string } }>(response)) ?? {}\n const transaction = body.transaction\n expect(transaction?.id, 'Gateway transaction payload is required').toBeTruthy()\n return {\n id: transaction!.id,\n providerSessionId: transaction?.providerSessionId ?? null,\n unifiedStatus: transaction?.unifiedStatus ?? 'unknown',\n }\n}\n\nexport async function sendMockGatewayWebhook(\n request: APIRequestContext,\n token: string,\n providerSessionId: string,\n status: 'captured' | 'cancelled' | 'failed',\n amount: number,\n options?: { providerKey?: string },\n): Promise<APIResponse> {\n const provider = encodeURIComponent(options?.providerKey ?? 'mock')\n const payload = {\n type: `payment.${status}`,\n id: uniqueLabel(`mock-${status}`),\n data: {\n id: providerSessionId,\n status,\n amount,\n },\n }\n const rawBody = JSON.stringify(payload)\n const signature = createHmac('sha256', MOCK_GATEWAY_DEV_WEBHOOK_SECRET)\n .update(rawBody, 'utf-8')\n .digest('hex')\n const BASE_URL = process.env.BASE_URL?.trim() || ''\n return request.fetch(`${BASE_URL}/api/payment_gateways/webhook/${provider}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n [MOCK_GATEWAY_SIGNATURE_HEADER]: signature,\n Authorization: `Bearer ${token}`,\n },\n data: rawBody,\n })\n}\n\nexport async function deleteCheckoutEntityIfExists(\n request: APIRequestContext,\n token: string | null,\n kind: 'templates' | 'links',\n id: string | null,\n): Promise<void> {\n if (!token || !id) return\n try {\n await apiRequest(request, 'DELETE', `/api/checkout/${kind}/${encodeURIComponent(id)}`, { token })\n } catch {\n return\n }\n}\n\nexport async function loginToBackendAndOpen(page: Page, path: string): Promise<void> {\n await page.goto('/login')\n await page.getByLabel('Email').fill('admin@acme.com')\n await page.getByLabel('Password').fill('secret')\n await page.getByRole('button', { name: /sign in/i }).click()\n await page.waitForURL(/\\/backend(?:\\/.*)?$/)\n await page.goto(path)\n}\n\nexport async function clearCapturedExampleEvents(\n request: APIRequestContext,\n token: string,\n): Promise<void> {\n const response = await apiRequest(request, 'DELETE', '/api/example/qa-events', { token })\n expect(response.ok(), `Failed to clear captured example events: ${response.status()}`).toBeTruthy()\n}\n\nexport async function listCapturedExampleEvents(\n request: APIRequestContext,\n token: string,\n options?: { event?: string; prefix?: string },\n): Promise<ExampleCapturedEvent[]> {\n const query = new URLSearchParams()\n if (options?.event) query.set('event', options.event)\n if (options?.prefix) query.set('prefix', options.prefix)\n const response = await apiRequest(request, 'GET', `/api/example/qa-events${query.size > 0 ? `?${query.toString()}` : ''}`, {\n token,\n })\n expect(response.ok(), `Failed to list captured example events: ${response.status()}`).toBeTruthy()\n const body = await readJsonSafe<{ items?: ExampleCapturedEvent[] }>(response)\n return Array.isArray(body?.items) ? body.items : []\n}\n\nexport async function waitForCapturedExampleEvents(\n request: APIRequestContext,\n token: string,\n expectedEventNames: string[],\n): Promise<ExampleCapturedEvent[]> {\n for (let attempt = 0; attempt < 30; attempt += 1) {\n const events = await listCapturedExampleEvents(request, token)\n const seenNames = new Set(events.map((event) => event.event))\n if (expectedEventNames.every((eventName) => seenNames.has(eventName))) {\n return events\n }\n await new Promise((resolve) => setTimeout(resolve, 150))\n }\n return listCapturedExampleEvents(request, token)\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { createHmac } from 'node:crypto'\nimport { expect, type APIRequestContext, type APIResponse, type Page } from '@playwright/test'\nimport { apiRequest } from '@open-mercato/core/modules/core/__integration__/helpers/api'\nimport {\n readJsonSafe,\n} from '@open-mercato/core/modules/core/__integration__/helpers/generalFixtures'\nimport type { PublicSubmitInput } from '../../data/validators'\n\nconst MOCK_GATEWAY_DEV_WEBHOOK_SECRET = 'open-mercato-mock-dev-webhook-secret'\nconst MOCK_GATEWAY_SIGNATURE_HEADER = 'x-mock-signature'\n\ntype JsonRecord = Record<string, unknown>\n\nlet forwardedIpSequence = Math.floor(Math.random() * 10_000)\n\nexport type CheckoutTemplateInput = {\n name: string\n title?: string | null\n subtitle?: string | null\n description?: string | null\n pricingMode: 'fixed' | 'custom_amount' | 'price_list'\n fixedPriceAmount?: number | null\n fixedPriceCurrencyCode?: string | null\n fixedPriceIncludesTax?: boolean\n fixedPriceOriginalAmount?: number | null\n customAmountMin?: number | null\n customAmountMax?: number | null\n customAmountCurrencyCode?: string | null\n priceListItems?: Array<{\n id: string\n description: string\n amount: number\n currencyCode: string\n }> | null\n gatewayProviderKey: string\n gatewaySettings?: Record<string, unknown>\n customFieldsetCode?: string | null\n collectCustomerDetails?: boolean\n legalDocuments?: {\n terms?: { title: string; markdown: string; required?: boolean }\n privacyPolicy?: { title: string; markdown: string; required?: boolean }\n }\n displayCustomFieldsOnPage?: boolean\n password?: string | null\n maxCompletions?: number | null\n status?: 'draft' | 'active' | 'inactive'\n customFields?: Record<string, unknown>\n}\n\nexport type CheckoutLinkInput = CheckoutTemplateInput & {\n templateId?: string | null\n slug?: string | null\n}\n\nexport type CheckoutLinkRecord = {\n id: string\n slug: string\n name?: string\n title?: string | null\n subtitle?: string | null\n status?: string\n templateId?: string | null\n completionCount?: number\n activeReservationCount?: number\n fixedPriceAmount?: number | null\n displayCustomFieldsOnPage?: boolean\n publicCustomFields?: Array<{ key?: string; label?: string; value?: unknown }>\n customerFieldsSchema?: Array<{ key: string; required?: boolean }>\n requiresPassword?: boolean\n available?: boolean\n remainingUses?: number | null\n gatewayProviderKey?: string | null\n customFields?: Record<string, unknown>\n}\n\nexport type CheckoutTransactionRecord = {\n id: string\n linkId?: string\n status: string\n paymentStatus?: string | null\n gatewayTransactionId?: string | null\n email?: string | null\n firstName?: string | null\n lastName?: string | null\n phone?: string | null\n acceptedLegalConsents?: Record<string, unknown> | null\n customerData?: Record<string, unknown> | null\n}\n\nexport type ExampleCapturedEvent = {\n event: string\n payload: Record<string, unknown>\n capturedAt: string\n}\n\nfunction uniqueLabel(prefix: string): string {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`\n}\n\nfunction createUniqueForwardedIp(): string {\n forwardedIpSequence += 1\n const thirdOctet = Math.floor(forwardedIpSequence / 250) % 250 + 1\n const fourthOctet = forwardedIpSequence % 250 + 1\n return `198.51.${thirdOctet}.${fourthOctet}`\n}\n\nexport function createCheckoutClientHeaders(overrides: Record<string, string> = {}): Record<string, string> {\n if (overrides['x-forwarded-for'] || overrides['x-real-ip']) {\n return overrides\n }\n return {\n 'x-forwarded-for': createUniqueForwardedIp(),\n ...overrides,\n }\n}\n\nexport function createFixedTemplateInput(overrides: Partial<CheckoutLinkInput> = {}): CheckoutLinkInput {\n const label = uniqueLabel('checkout-fixed')\n return {\n name: `QA ${label}`,\n title: `QA ${label}`,\n subtitle: 'QA checkout fixture',\n description: 'QA checkout fixture description',\n pricingMode: 'fixed',\n fixedPriceAmount: 49.99,\n fixedPriceCurrencyCode: 'USD',\n fixedPriceIncludesTax: true,\n fixedPriceOriginalAmount: 69.99,\n gatewayProviderKey: 'mock',\n status: 'draft',\n collectCustomerDetails: true,\n displayCustomFieldsOnPage: false,\n ...overrides,\n }\n}\n\nexport function createCustomAmountTemplateInput(overrides: Partial<CheckoutLinkInput> = {}): CheckoutLinkInput {\n const label = uniqueLabel('checkout-custom')\n return {\n name: `QA ${label}`,\n title: `QA ${label}`,\n subtitle: 'QA custom amount fixture',\n description: 'QA custom amount description',\n pricingMode: 'custom_amount',\n customAmountMin: 10,\n customAmountMax: 100,\n customAmountCurrencyCode: 'USD',\n gatewayProviderKey: 'mock',\n status: 'active',\n collectCustomerDetails: true,\n displayCustomFieldsOnPage: false,\n ...overrides,\n }\n}\n\nexport function createPriceListTemplateInput(overrides: Partial<CheckoutLinkInput> = {}): CheckoutLinkInput {\n const label = uniqueLabel('checkout-price-list')\n return {\n name: `QA ${label}`,\n title: `QA ${label}`,\n subtitle: 'QA price list fixture',\n description: 'QA price list description',\n pricingMode: 'price_list',\n priceListItems: [\n { id: 'basic', description: 'Basic', amount: 19.99, currencyCode: 'USD' },\n { id: 'plus', description: 'Plus', amount: 49.99, currencyCode: 'USD' },\n ],\n gatewayProviderKey: 'mock',\n status: 'active',\n collectCustomerDetails: true,\n displayCustomFieldsOnPage: false,\n ...overrides,\n }\n}\n\nexport function createCustomerData(overrides: Record<string, unknown> = {}): Record<string, unknown> {\n const label = uniqueLabel('customer')\n return {\n firstName: 'Quinn',\n lastName: 'Checkout',\n email: `${label}@example.test`,\n phone: '+15550001111',\n ...overrides,\n }\n}\n\nexport async function createTemplateFixture(\n request: APIRequestContext,\n token: string,\n input: CheckoutTemplateInput,\n): Promise<string> {\n const response = await apiRequest(request, 'POST', '/api/checkout/templates', {\n token,\n data: input,\n })\n const body = await readJsonSafe<{ id?: string }>(response)\n expect(\n response.ok(),\n `Failed to create template: ${response.status()} ${JSON.stringify(body)}`,\n ).toBeTruthy()\n expect(typeof body?.id === 'string' && body.id.length > 0, 'Template id is required').toBeTruthy()\n return body!.id!\n}\n\nexport async function createLinkFixture(\n request: APIRequestContext,\n token: string,\n input: CheckoutLinkInput,\n): Promise<{ id: string; slug: string }> {\n const response = await apiRequest(request, 'POST', '/api/checkout/links', {\n token,\n data: input,\n })\n const body = await readJsonSafe<{ id?: string; slug?: string }>(response)\n expect(\n response.ok(),\n `Failed to create link: ${response.status()} ${JSON.stringify(body)}`,\n ).toBeTruthy()\n expect(typeof body?.id === 'string' && body.id.length > 0, 'Link id is required').toBeTruthy()\n expect(typeof body?.slug === 'string' && body.slug.length > 0, 'Link slug is required').toBeTruthy()\n return { id: body!.id!, slug: body!.slug! }\n}\n\nexport async function readTemplate(\n request: APIRequestContext,\n token: string,\n templateId: string,\n): Promise<JsonRecord> {\n const response = await apiRequest(request, 'GET', `/api/checkout/templates/${encodeURIComponent(templateId)}`, { token })\n expect(response.ok(), `Failed to read template ${templateId}: ${response.status()}`).toBeTruthy()\n return (await readJsonSafe<JsonRecord>(response)) ?? {}\n}\n\nexport async function readLink(\n request: APIRequestContext,\n token: string,\n linkId: string,\n): Promise<CheckoutLinkRecord> {\n const response = await apiRequest(request, 'GET', `/api/checkout/links/${encodeURIComponent(linkId)}`, { token })\n expect(response.ok(), `Failed to read link ${linkId}: ${response.status()}`).toBeTruthy()\n return ((await readJsonSafe<CheckoutLinkRecord>(response)) ?? {}) as CheckoutLinkRecord\n}\n\nexport async function updateTemplate(\n request: APIRequestContext,\n token: string,\n templateId: string,\n data: Record<string, unknown>,\n): Promise<APIResponse> {\n return apiRequest(request, 'PUT', `/api/checkout/templates/${encodeURIComponent(templateId)}`, {\n token,\n data,\n })\n}\n\nexport async function updateLink(\n request: APIRequestContext,\n token: string,\n linkId: string,\n data: Record<string, unknown>,\n): Promise<APIResponse> {\n return apiRequest(request, 'PUT', `/api/checkout/links/${encodeURIComponent(linkId)}`, {\n token,\n data,\n })\n}\n\nexport async function deleteTemplate(\n request: APIRequestContext,\n token: string,\n templateId: string,\n): Promise<APIResponse> {\n return apiRequest(request, 'DELETE', `/api/checkout/templates/${encodeURIComponent(templateId)}`, { token })\n}\n\nexport async function deleteLink(\n request: APIRequestContext,\n token: string,\n linkId: string,\n): Promise<APIResponse> {\n return apiRequest(request, 'DELETE', `/api/checkout/links/${encodeURIComponent(linkId)}`, { token })\n}\n\nexport async function listTemplates(\n request: APIRequestContext,\n token: string,\n query = '',\n): Promise<{ items: JsonRecord[]; total: number }> {\n const response = await apiRequest(request, 'GET', `/api/checkout/templates${query ? `?${query}` : ''}`, { token })\n expect(response.ok(), `Failed to list templates: ${response.status()}`).toBeTruthy()\n return ((await readJsonSafe<{ items?: JsonRecord[]; total?: number }>(response)) ?? {\n items: [],\n total: 0,\n }) as { items: JsonRecord[]; total: number }\n}\n\nexport async function listLinks(\n request: APIRequestContext,\n token: string,\n query = '',\n): Promise<{ items: JsonRecord[]; total: number }> {\n const response = await apiRequest(request, 'GET', `/api/checkout/links${query ? `?${query}` : ''}`, { token })\n expect(response.ok(), `Failed to list links: ${response.status()}`).toBeTruthy()\n return ((await readJsonSafe<{ items?: JsonRecord[]; total?: number }>(response)) ?? {\n items: [],\n total: 0,\n }) as { items: JsonRecord[]; total: number }\n}\n\nexport async function readPublicPayLink(\n request: APIRequestContext,\n slug: string,\n options?: { headers?: Record<string, string>; preview?: boolean },\n): Promise<APIResponse> {\n const query = options?.preview ? '?preview=true' : ''\n return request.fetch(`${process.env.BASE_URL || 'http://localhost:3000'}/api/checkout/pay/${encodeURIComponent(slug)}${query}`, {\n method: 'GET',\n headers: createCheckoutClientHeaders(options?.headers),\n })\n}\n\nexport async function verifyPayLinkPassword(\n request: APIRequestContext,\n slug: string,\n password: string,\n): Promise<APIResponse> {\n return request.fetch(`${process.env.BASE_URL || 'http://localhost:3000'}/api/checkout/pay/${encodeURIComponent(slug)}/verify-password`, {\n method: 'POST',\n headers: createCheckoutClientHeaders({ 'Content-Type': 'application/json' }),\n data: { password },\n })\n}\n\nexport async function submitPayLink(\n request: APIRequestContext,\n slug: string,\n input: PublicSubmitInput,\n options?: { idempotencyKey?: string; headers?: Record<string, string> },\n): Promise<APIResponse> {\n return request.fetch(`${process.env.BASE_URL || 'http://localhost:3000'}/api/checkout/pay/${encodeURIComponent(slug)}/submit`, {\n method: 'POST',\n headers: createCheckoutClientHeaders({\n 'Content-Type': 'application/json',\n 'Idempotency-Key': options?.idempotencyKey ?? uniqueLabel('idempotency'),\n ...(options?.headers ?? {}),\n }),\n data: input,\n })\n}\n\nexport async function readCheckoutTransaction(\n request: APIRequestContext,\n token: string,\n transactionId: string,\n): Promise<CheckoutTransactionRecord> {\n const response = await apiRequest(request, 'GET', `/api/checkout/transactions/${encodeURIComponent(transactionId)}`, { token })\n expect(response.ok(), `Failed to read transaction ${transactionId}: ${response.status()}`).toBeTruthy()\n const body = (await readJsonSafe<{ transaction?: CheckoutTransactionRecord }>(response)) ?? {}\n return (body.transaction ?? {}) as CheckoutTransactionRecord\n}\n\nexport async function listCheckoutTransactions(\n request: APIRequestContext,\n token: string,\n query = '',\n): Promise<{ items: CheckoutTransactionRecord[]; total: number; canViewPii?: boolean }> {\n const response = await apiRequest(request, 'GET', `/api/checkout/transactions${query ? `?${query}` : ''}`, { token })\n expect(response.ok(), `Failed to list checkout transactions: ${response.status()}`).toBeTruthy()\n return ((await readJsonSafe<{ items?: CheckoutTransactionRecord[]; total?: number; canViewPii?: boolean }>(response)) ?? {\n items: [],\n total: 0,\n }) as { items: CheckoutTransactionRecord[]; total: number; canViewPii?: boolean }\n}\n\nexport async function readCheckoutStatus(\n request: APIRequestContext,\n slug: string,\n transactionId: string,\n options?: { headers?: Record<string, string> },\n): Promise<APIResponse> {\n return request.fetch(\n `${process.env.BASE_URL || 'http://localhost:3000'}/api/checkout/pay/${encodeURIComponent(slug)}/status/${encodeURIComponent(transactionId)}`,\n {\n method: 'GET',\n headers: createCheckoutClientHeaders(options?.headers),\n },\n )\n}\n\nexport async function waitForCheckoutStatus(\n request: APIRequestContext,\n token: string,\n transactionId: string,\n expectedStatus: string,\n): Promise<CheckoutTransactionRecord> {\n for (let attempt = 0; attempt < 20; attempt += 1) {\n const transaction = await readCheckoutTransaction(request, token, transactionId)\n if (transaction.status === expectedStatus) return transaction\n await new Promise((resolve) => setTimeout(resolve, 150))\n }\n return readCheckoutTransaction(request, token, transactionId)\n}\n\nexport async function findGatewayTransactionIdForCheckout(\n request: APIRequestContext,\n token: string,\n checkoutTransactionId: string,\n): Promise<string> {\n const response = await apiRequest(request, 'GET', '/api/payment_gateways/transactions?page=1&pageSize=100', { token })\n expect(response.ok(), `Failed to list gateway transactions: ${response.status()}`).toBeTruthy()\n const body = (await readJsonSafe<{ items?: Array<{ id: string; paymentId: string }> }>(response)) ?? {}\n const match = body.items?.find((item) => item.paymentId === checkoutTransactionId)\n expect(match, `Gateway transaction for checkout ${checkoutTransactionId} was not found`).toBeTruthy()\n return match!.id\n}\n\nexport async function readGatewayTransaction(\n request: APIRequestContext,\n token: string,\n gatewayTransactionId: string,\n): Promise<{\n id: string\n providerSessionId: string | null\n unifiedStatus: string\n}> {\n const response = await apiRequest(request, 'GET', `/api/payment_gateways/transactions/${encodeURIComponent(gatewayTransactionId)}`, { token })\n expect(response.ok(), `Failed to read gateway transaction ${gatewayTransactionId}: ${response.status()}`).toBeTruthy()\n const body = (await readJsonSafe<{ transaction?: { id: string; providerSessionId?: string | null; unifiedStatus?: string } }>(response)) ?? {}\n const transaction = body.transaction\n expect(transaction?.id, 'Gateway transaction payload is required').toBeTruthy()\n return {\n id: transaction!.id,\n providerSessionId: transaction?.providerSessionId ?? null,\n unifiedStatus: transaction?.unifiedStatus ?? 'unknown',\n }\n}\n\nexport async function sendMockGatewayWebhook(\n request: APIRequestContext,\n token: string,\n providerSessionId: string,\n status: 'captured' | 'cancelled' | 'failed',\n amount: number,\n options?: { providerKey?: string },\n): Promise<APIResponse> {\n const provider = encodeURIComponent(options?.providerKey ?? 'mock')\n const payload = {\n type: `payment.${status}`,\n id: uniqueLabel(`mock-${status}`),\n data: {\n id: providerSessionId,\n status,\n amount,\n },\n }\n const rawBody = JSON.stringify(payload)\n const signature = createHmac('sha256', MOCK_GATEWAY_DEV_WEBHOOK_SECRET)\n .update(rawBody, 'utf-8')\n .digest('hex')\n const BASE_URL = process.env.BASE_URL?.trim() || ''\n return request.fetch(`${BASE_URL}/api/payment_gateways/webhook/${provider}`, {\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n [MOCK_GATEWAY_SIGNATURE_HEADER]: signature,\n Authorization: `Bearer ${token}`,\n },\n data: rawBody,\n })\n}\n\nexport async function deleteCheckoutEntityIfExists(\n request: APIRequestContext,\n token: string | null,\n kind: 'templates' | 'links',\n id: string | null,\n): Promise<void> {\n if (!token || !id) return\n try {\n await apiRequest(request, 'DELETE', `/api/checkout/${kind}/${encodeURIComponent(id)}`, { token })\n } catch {\n return\n }\n}\n\nexport async function loginToBackendAndOpen(page: Page, path: string): Promise<void> {\n await page.goto('/login')\n await page.getByLabel('Email').fill('admin@acme.com')\n await page.getByLabel('Password').fill('secret')\n await page.getByRole('button', { name: /sign in/i }).click()\n await page.waitForURL(/\\/backend(?:\\/.*)?$/)\n await page.goto(path)\n}\n\nexport async function clearCapturedExampleEvents(\n request: APIRequestContext,\n token: string,\n): Promise<void> {\n const response = await apiRequest(request, 'DELETE', '/api/example/qa-events', { token })\n expect(response.ok(), `Failed to clear captured example events: ${response.status()}`).toBeTruthy()\n}\n\nexport async function listCapturedExampleEvents(\n request: APIRequestContext,\n token: string,\n options?: { event?: string; prefix?: string },\n): Promise<ExampleCapturedEvent[]> {\n const query = new URLSearchParams()\n if (options?.event) query.set('event', options.event)\n if (options?.prefix) query.set('prefix', options.prefix)\n const response = await apiRequest(request, 'GET', `/api/example/qa-events${query.size > 0 ? `?${query.toString()}` : ''}`, {\n token,\n })\n expect(response.ok(), `Failed to list captured example events: ${response.status()}`).toBeTruthy()\n const body = await readJsonSafe<{ items?: ExampleCapturedEvent[] }>(response)\n return Array.isArray(body?.items) ? body.items : []\n}\n\nexport async function waitForCapturedExampleEvents(\n request: APIRequestContext,\n token: string,\n expectedEventNames: string[],\n): Promise<ExampleCapturedEvent[]> {\n for (let attempt = 0; attempt < 30; attempt += 1) {\n const events = await listCapturedExampleEvents(request, token)\n const seenNames = new Set(events.map((event) => event.event))\n if (expectedEventNames.every((eventName) => seenNames.has(eventName))) {\n return events\n }\n await new Promise((resolve) => setTimeout(resolve, 150))\n }\n return listCapturedExampleEvents(request, token)\n}\n"],
5
+ "mappings": "AAAA,SAAS,kBAAkB;AAC3B,SAAS,cAAmE;AAC5E,SAAS,kBAAkB;AAC3B;AAAA,EACE;AAAA,OACK;AAGP,MAAM,kCAAkC;AACxC,MAAM,gCAAgC;AAItC,IAAI,sBAAsB,KAAK,MAAM,KAAK,OAAO,IAAI,GAAM;AAkF3D,SAAS,YAAY,QAAwB;AAC3C,SAAO,GAAG,MAAM,IAAI,KAAK,IAAI,CAAC,IAAI,KAAK,OAAO,EAAE,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAC1E;AAEA,SAAS,0BAAkC;AACzC,yBAAuB;AACvB,QAAM,aAAa,KAAK,MAAM,sBAAsB,GAAG,IAAI,MAAM;AACjE,QAAM,cAAc,sBAAsB,MAAM;AAChD,SAAO,UAAU,UAAU,IAAI,WAAW;AAC5C;AAEO,SAAS,4BAA4B,YAAoC,CAAC,GAA2B;AAC1G,MAAI,UAAU,iBAAiB,KAAK,UAAU,WAAW,GAAG;AAC1D,WAAO;AAAA,EACT;AACA,SAAO;AAAA,IACL,mBAAmB,wBAAwB;AAAA,IAC3C,GAAG;AAAA,EACL;AACF;AAEO,SAAS,yBAAyB,YAAwC,CAAC,GAAsB;AACtG,QAAM,QAAQ,YAAY,gBAAgB;AAC1C,SAAO;AAAA,IACL,MAAM,MAAM,KAAK;AAAA,IACjB,OAAO,MAAM,KAAK;AAAA,IAClB,UAAU;AAAA,IACV,aAAa;AAAA,IACb,aAAa;AAAA,IACb,kBAAkB;AAAA,IAClB,wBAAwB;AAAA,IACxB,uBAAuB;AAAA,IACvB,0BAA0B;AAAA,IAC1B,oBAAoB;AAAA,IACpB,QAAQ;AAAA,IACR,wBAAwB;AAAA,IACxB,2BAA2B;AAAA,IAC3B,GAAG;AAAA,EACL;AACF;AAEO,SAAS,gCAAgC,YAAwC,CAAC,GAAsB;AAC7G,QAAM,QAAQ,YAAY,iBAAiB;AAC3C,SAAO;AAAA,IACL,MAAM,MAAM,KAAK;AAAA,IACjB,OAAO,MAAM,KAAK;AAAA,IAClB,UAAU;AAAA,IACV,aAAa;AAAA,IACb,aAAa;AAAA,IACb,iBAAiB;AAAA,IACjB,iBAAiB;AAAA,IACjB,0BAA0B;AAAA,IAC1B,oBAAoB;AAAA,IACpB,QAAQ;AAAA,IACR,wBAAwB;AAAA,IACxB,2BAA2B;AAAA,IAC3B,GAAG;AAAA,EACL;AACF;AAEO,SAAS,6BAA6B,YAAwC,CAAC,GAAsB;AAC1G,QAAM,QAAQ,YAAY,qBAAqB;AAC/C,SAAO;AAAA,IACL,MAAM,MAAM,KAAK;AAAA,IACjB,OAAO,MAAM,KAAK;AAAA,IAClB,UAAU;AAAA,IACV,aAAa;AAAA,IACb,aAAa;AAAA,IACb,gBAAgB;AAAA,MACd,EAAE,IAAI,SAAS,aAAa,SAAS,QAAQ,OAAO,cAAc,MAAM;AAAA,MACxE,EAAE,IAAI,QAAQ,aAAa,QAAQ,QAAQ,OAAO,cAAc,MAAM;AAAA,IACxE;AAAA,IACA,oBAAoB;AAAA,IACpB,QAAQ;AAAA,IACR,wBAAwB;AAAA,IACxB,2BAA2B;AAAA,IAC3B,GAAG;AAAA,EACL;AACF;AAEO,SAAS,mBAAmB,YAAqC,CAAC,GAA4B;AACnG,QAAM,QAAQ,YAAY,UAAU;AACpC,SAAO;AAAA,IACL,WAAW;AAAA,IACX,UAAU;AAAA,IACV,OAAO,GAAG,KAAK;AAAA,IACf,OAAO;AAAA,IACP,GAAG;AAAA,EACL;AACF;AAEA,eAAsB,sBACpB,SACA,OACA,OACiB;AACjB,QAAM,WAAW,MAAM,WAAW,SAAS,QAAQ,2BAA2B;AAAA,IAC5E;AAAA,IACA,MAAM;AAAA,EACR,CAAC;AACD,QAAM,OAAO,MAAM,aAA8B,QAAQ;AACzD;AAAA,IACE,SAAS,GAAG;AAAA,IACZ,8BAA8B,SAAS,OAAO,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,EACzE,EAAE,WAAW;AACb,SAAO,OAAO,MAAM,OAAO,YAAY,KAAK,GAAG,SAAS,GAAG,yBAAyB,EAAE,WAAW;AACjG,SAAO,KAAM;AACf;AAEA,eAAsB,kBACpB,SACA,OACA,OACuC;AACvC,QAAM,WAAW,MAAM,WAAW,SAAS,QAAQ,uBAAuB;AAAA,IACxE;AAAA,IACA,MAAM;AAAA,EACR,CAAC;AACD,QAAM,OAAO,MAAM,aAA6C,QAAQ;AACxE;AAAA,IACE,SAAS,GAAG;AAAA,IACZ,0BAA0B,SAAS,OAAO,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC;AAAA,EACrE,EAAE,WAAW;AACb,SAAO,OAAO,MAAM,OAAO,YAAY,KAAK,GAAG,SAAS,GAAG,qBAAqB,EAAE,WAAW;AAC7F,SAAO,OAAO,MAAM,SAAS,YAAY,KAAK,KAAK,SAAS,GAAG,uBAAuB,EAAE,WAAW;AACnG,SAAO,EAAE,IAAI,KAAM,IAAK,MAAM,KAAM,KAAM;AAC5C;AAEA,eAAsB,aACpB,SACA,OACA,YACqB;AACrB,QAAM,WAAW,MAAM,WAAW,SAAS,OAAO,2BAA2B,mBAAmB,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC;AACxH,SAAO,SAAS,GAAG,GAAG,2BAA2B,UAAU,KAAK,SAAS,OAAO,CAAC,EAAE,EAAE,WAAW;AAChG,SAAQ,MAAM,aAAyB,QAAQ,KAAM,CAAC;AACxD;AAEA,eAAsB,SACpB,SACA,OACA,QAC6B;AAC7B,QAAM,WAAW,MAAM,WAAW,SAAS,OAAO,uBAAuB,mBAAmB,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC;AAChH,SAAO,SAAS,GAAG,GAAG,uBAAuB,MAAM,KAAK,SAAS,OAAO,CAAC,EAAE,EAAE,WAAW;AACxF,SAAS,MAAM,aAAiC,QAAQ,KAAM,CAAC;AACjE;AAEA,eAAsB,eACpB,SACA,OACA,YACA,MACsB;AACtB,SAAO,WAAW,SAAS,OAAO,2BAA2B,mBAAmB,UAAU,CAAC,IAAI;AAAA,IAC7F;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEA,eAAsB,WACpB,SACA,OACA,QACA,MACsB;AACtB,SAAO,WAAW,SAAS,OAAO,uBAAuB,mBAAmB,MAAM,CAAC,IAAI;AAAA,IACrF;AAAA,IACA;AAAA,EACF,CAAC;AACH;AAEA,eAAsB,eACpB,SACA,OACA,YACsB;AACtB,SAAO,WAAW,SAAS,UAAU,2BAA2B,mBAAmB,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC;AAC7G;AAEA,eAAsB,WACpB,SACA,OACA,QACsB;AACtB,SAAO,WAAW,SAAS,UAAU,uBAAuB,mBAAmB,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC;AACrG;AAEA,eAAsB,cACpB,SACA,OACA,QAAQ,IACyC;AACjD,QAAM,WAAW,MAAM,WAAW,SAAS,OAAO,0BAA0B,QAAQ,IAAI,KAAK,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC;AACjH,SAAO,SAAS,GAAG,GAAG,6BAA6B,SAAS,OAAO,CAAC,EAAE,EAAE,WAAW;AACnF,SAAS,MAAM,aAAuD,QAAQ,KAAM;AAAA,IAClF,OAAO,CAAC;AAAA,IACR,OAAO;AAAA,EACT;AACF;AAEA,eAAsB,UACpB,SACA,OACA,QAAQ,IACyC;AACjD,QAAM,WAAW,MAAM,WAAW,SAAS,OAAO,sBAAsB,QAAQ,IAAI,KAAK,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC;AAC7G,SAAO,SAAS,GAAG,GAAG,yBAAyB,SAAS,OAAO,CAAC,EAAE,EAAE,WAAW;AAC/E,SAAS,MAAM,aAAuD,QAAQ,KAAM;AAAA,IAClF,OAAO,CAAC;AAAA,IACR,OAAO;AAAA,EACT;AACF;AAEA,eAAsB,kBACpB,SACA,MACA,SACsB;AACtB,QAAM,QAAQ,SAAS,UAAU,kBAAkB;AACnD,SAAO,QAAQ,MAAM,GAAG,QAAQ,IAAI,YAAY,uBAAuB,qBAAqB,mBAAmB,IAAI,CAAC,GAAG,KAAK,IAAI;AAAA,IAC9H,QAAQ;AAAA,IACR,SAAS,4BAA4B,SAAS,OAAO;AAAA,EACvD,CAAC;AACH;AAEA,eAAsB,sBACpB,SACA,MACA,UACsB;AACtB,SAAO,QAAQ,MAAM,GAAG,QAAQ,IAAI,YAAY,uBAAuB,qBAAqB,mBAAmB,IAAI,CAAC,oBAAoB;AAAA,IACtI,QAAQ;AAAA,IACR,SAAS,4BAA4B,EAAE,gBAAgB,mBAAmB,CAAC;AAAA,IAC3E,MAAM,EAAE,SAAS;AAAA,EACnB,CAAC;AACH;AAEA,eAAsB,cACpB,SACA,MACA,OACA,SACsB;AACtB,SAAO,QAAQ,MAAM,GAAG,QAAQ,IAAI,YAAY,uBAAuB,qBAAqB,mBAAmB,IAAI,CAAC,WAAW;AAAA,IAC7H,QAAQ;AAAA,IACR,SAAS,4BAA4B;AAAA,MACnC,gBAAgB;AAAA,MAChB,mBAAmB,SAAS,kBAAkB,YAAY,aAAa;AAAA,MACvE,GAAI,SAAS,WAAW,CAAC;AAAA,IAC3B,CAAC;AAAA,IACD,MAAM;AAAA,EACR,CAAC;AACH;AAEA,eAAsB,wBACpB,SACA,OACA,eACoC;AACpC,QAAM,WAAW,MAAM,WAAW,SAAS,OAAO,8BAA8B,mBAAmB,aAAa,CAAC,IAAI,EAAE,MAAM,CAAC;AAC9H,SAAO,SAAS,GAAG,GAAG,8BAA8B,aAAa,KAAK,SAAS,OAAO,CAAC,EAAE,EAAE,WAAW;AACtG,QAAM,OAAQ,MAAM,aAA0D,QAAQ,KAAM,CAAC;AAC7F,SAAQ,KAAK,eAAe,CAAC;AAC/B;AAEA,eAAsB,yBACpB,SACA,OACA,QAAQ,IAC8E;AACtF,QAAM,WAAW,MAAM,WAAW,SAAS,OAAO,6BAA6B,QAAQ,IAAI,KAAK,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC;AACpH,SAAO,SAAS,GAAG,GAAG,yCAAyC,SAAS,OAAO,CAAC,EAAE,EAAE,WAAW;AAC/F,SAAS,MAAM,aAA4F,QAAQ,KAAM;AAAA,IACvH,OAAO,CAAC;AAAA,IACR,OAAO;AAAA,EACT;AACF;AAEA,eAAsB,mBACpB,SACA,MACA,eACA,SACsB;AACtB,SAAO,QAAQ;AAAA,IACb,GAAG,QAAQ,IAAI,YAAY,uBAAuB,qBAAqB,mBAAmB,IAAI,CAAC,WAAW,mBAAmB,aAAa,CAAC;AAAA,IAC3I;AAAA,MACE,QAAQ;AAAA,MACR,SAAS,4BAA4B,SAAS,OAAO;AAAA,IACvD;AAAA,EACF;AACF;AAEA,eAAsB,sBACpB,SACA,OACA,eACA,gBACoC;AACpC,WAAS,UAAU,GAAG,UAAU,IAAI,WAAW,GAAG;AAChD,UAAM,cAAc,MAAM,wBAAwB,SAAS,OAAO,aAAa;AAC/E,QAAI,YAAY,WAAW,eAAgB,QAAO;AAClD,UAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAG,CAAC;AAAA,EACzD;AACA,SAAO,wBAAwB,SAAS,OAAO,aAAa;AAC9D;AAEA,eAAsB,oCACpB,SACA,OACA,uBACiB;AACjB,QAAM,WAAW,MAAM,WAAW,SAAS,OAAO,0DAA0D,EAAE,MAAM,CAAC;AACrH,SAAO,SAAS,GAAG,GAAG,wCAAwC,SAAS,OAAO,CAAC,EAAE,EAAE,WAAW;AAC9F,QAAM,OAAQ,MAAM,aAAmE,QAAQ,KAAM,CAAC;AACtG,QAAM,QAAQ,KAAK,OAAO,KAAK,CAAC,SAAS,KAAK,cAAc,qBAAqB;AACjF,SAAO,OAAO,oCAAoC,qBAAqB,gBAAgB,EAAE,WAAW;AACpG,SAAO,MAAO;AAChB;AAEA,eAAsB,uBACpB,SACA,OACA,sBAKC;AACD,QAAM,WAAW,MAAM,WAAW,SAAS,OAAO,sCAAsC,mBAAmB,oBAAoB,CAAC,IAAI,EAAE,MAAM,CAAC;AAC7I,SAAO,SAAS,GAAG,GAAG,sCAAsC,oBAAoB,KAAK,SAAS,OAAO,CAAC,EAAE,EAAE,WAAW;AACrH,QAAM,OAAQ,MAAM,aAA0G,QAAQ,KAAM,CAAC;AAC7I,QAAM,cAAc,KAAK;AACzB,SAAO,aAAa,IAAI,yCAAyC,EAAE,WAAW;AAC9E,SAAO;AAAA,IACL,IAAI,YAAa;AAAA,IACjB,mBAAmB,aAAa,qBAAqB;AAAA,IACrD,eAAe,aAAa,iBAAiB;AAAA,EAC/C;AACF;AAEA,eAAsB,uBACpB,SACA,OACA,mBACA,QACA,QACA,SACsB;AACtB,QAAM,WAAW,mBAAmB,SAAS,eAAe,MAAM;AAClE,QAAM,UAAU;AAAA,IACd,MAAM,WAAW,MAAM;AAAA,IACvB,IAAI,YAAY,QAAQ,MAAM,EAAE;AAAA,IAChC,MAAM;AAAA,MACJ,IAAI;AAAA,MACJ;AAAA,MACA;AAAA,IACF;AAAA,EACF;AACA,QAAM,UAAU,KAAK,UAAU,OAAO;AACtC,QAAM,YAAY,WAAW,UAAU,+BAA+B,EACnE,OAAO,SAAS,OAAO,EACvB,OAAO,KAAK;AACf,QAAM,WAAW,QAAQ,IAAI,UAAU,KAAK,KAAK;AACjD,SAAO,QAAQ,MAAM,GAAG,QAAQ,iCAAiC,QAAQ,IAAI;AAAA,IAC3E,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,gBAAgB;AAAA,MAChB,CAAC,6BAA6B,GAAG;AAAA,MACjC,eAAe,UAAU,KAAK;AAAA,IAChC;AAAA,IACA,MAAM;AAAA,EACR,CAAC;AACH;AAEA,eAAsB,6BACpB,SACA,OACA,MACA,IACe;AACf,MAAI,CAAC,SAAS,CAAC,GAAI;AACnB,MAAI;AACF,UAAM,WAAW,SAAS,UAAU,iBAAiB,IAAI,IAAI,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC;AAAA,EAClG,QAAQ;AACN;AAAA,EACF;AACF;AAEA,eAAsB,sBAAsB,MAAY,MAA6B;AACnF,QAAM,KAAK,KAAK,QAAQ;AACxB,QAAM,KAAK,WAAW,OAAO,EAAE,KAAK,gBAAgB;AACpD,QAAM,KAAK,WAAW,UAAU,EAAE,KAAK,QAAQ;AAC/C,QAAM,KAAK,UAAU,UAAU,EAAE,MAAM,WAAW,CAAC,EAAE,MAAM;AAC3D,QAAM,KAAK,WAAW,qBAAqB;AAC3C,QAAM,KAAK,KAAK,IAAI;AACtB;AAEA,eAAsB,2BACpB,SACA,OACe;AACf,QAAM,WAAW,MAAM,WAAW,SAAS,UAAU,0BAA0B,EAAE,MAAM,CAAC;AACxF,SAAO,SAAS,GAAG,GAAG,4CAA4C,SAAS,OAAO,CAAC,EAAE,EAAE,WAAW;AACpG;AAEA,eAAsB,0BACpB,SACA,OACA,SACiC;AACjC,QAAM,QAAQ,IAAI,gBAAgB;AAClC,MAAI,SAAS,MAAO,OAAM,IAAI,SAAS,QAAQ,KAAK;AACpD,MAAI,SAAS,OAAQ,OAAM,IAAI,UAAU,QAAQ,MAAM;AACvD,QAAM,WAAW,MAAM,WAAW,SAAS,OAAO,yBAAyB,MAAM,OAAO,IAAI,IAAI,MAAM,SAAS,CAAC,KAAK,EAAE,IAAI;AAAA,IACzH;AAAA,EACF,CAAC;AACD,SAAO,SAAS,GAAG,GAAG,2CAA2C,SAAS,OAAO,CAAC,EAAE,EAAE,WAAW;AACjG,QAAM,OAAO,MAAM,aAAiD,QAAQ;AAC5E,SAAO,MAAM,QAAQ,MAAM,KAAK,IAAI,KAAK,QAAQ,CAAC;AACpD;AAEA,eAAsB,6BACpB,SACA,OACA,oBACiC;AACjC,WAAS,UAAU,GAAG,UAAU,IAAI,WAAW,GAAG;AAChD,UAAM,SAAS,MAAM,0BAA0B,SAAS,KAAK;AAC7D,UAAM,YAAY,IAAI,IAAI,OAAO,IAAI,CAAC,UAAU,MAAM,KAAK,CAAC;AAC5D,QAAI,mBAAmB,MAAM,CAAC,cAAc,UAAU,IAAI,SAAS,CAAC,GAAG;AACrE,aAAO;AAAA,IACT;AACA,UAAM,IAAI,QAAQ,CAAC,YAAY,WAAW,SAAS,GAAG,CAAC;AAAA,EACzD;AACA,SAAO,0BAA0B,SAAS,KAAK;AACjD;",
6
6
  "names": []
7
7
  }
@@ -25,20 +25,11 @@ const hexColorSchema = z.string().regex(/^#([0-9a-fA-F]{6})$/, {
25
25
  const currencyCodeSchema = z.string().trim().toUpperCase().regex(/^[A-Z]{3}$/, {
26
26
  message: "checkout.validation.common.invalidCurrencyCode"
27
27
  });
28
- const optionalTrimmedString = z.preprocess(
29
- normalizeBlankString,
30
- z.string().trim().min(1, { message: "checkout.validation.common.required" }).optional().nullable()
31
- ).optional();
32
- const optionalUrlSchema = z.preprocess(
33
- normalizeBlankString,
34
- z.string().url("checkout.validation.common.invalidUrl").optional().nullable()
35
- ).optional();
36
- const optionalFieldsetCodeSchema = z.preprocess(
37
- normalizeBlankString,
38
- z.string().regex(fieldsetCodeRegex, {
39
- message: "checkout.validation.common.invalidFieldsetCode"
40
- }).optional().nullable()
41
- ).optional();
28
+ const optionalTrimmedString = z.union([z.string(), z.null(), z.undefined()]).transform(normalizeBlankString).pipe(z.string().trim().min(1, { message: "checkout.validation.common.required" }).optional().nullable());
29
+ const optionalUrlSchema = z.union([z.string(), z.null(), z.undefined()]).transform(normalizeBlankString).pipe(z.string().url("checkout.validation.common.invalidUrl").optional().nullable());
30
+ const optionalFieldsetCodeSchema = z.union([z.string(), z.null(), z.undefined()]).transform(normalizeBlankString).pipe(z.string().regex(fieldsetCodeRegex, {
31
+ message: "checkout.validation.common.invalidFieldsetCode"
32
+ }).optional().nullable());
42
33
  const positiveMoneySchema = z.coerce.number().finite("checkout.validation.common.invalidNumber").nonnegative("checkout.validation.common.nonNegativeNumber");
43
34
  const linkStatusSchema = z.enum(CHECKOUT_LINK_STATUSES);
44
35
  const customerFieldOptionSchema = z.object({
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/checkout/data/validators.ts"],
4
- "sourcesContent": ["import { z } from 'zod'\nimport { fieldsetCodeRegex } from '@open-mercato/shared/modules/entities/validators'\nimport { DEFAULT_CHECKOUT_CUSTOMER_FIELDS } from '../lib/defaults'\nimport { CHECKOUT_LINK_STATUSES } from '../lib/constants'\n\nfunction normalizeBlankString(value: unknown): unknown {\n if (typeof value !== 'string') return value\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : null\n}\n\nfunction normalizeOptionalDocument(value: unknown): unknown {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return value\n const source = value as Record<string, unknown>\n const title = typeof source.title === 'string' ? source.title.trim() : ''\n const markdown = typeof source.markdown === 'string' ? source.markdown.trim() : ''\n const required = source.required === true\n if (!title && !markdown && !required) return undefined\n return value\n}\n\nfunction requiredTrimmedString(message: string) {\n return z.string().trim().min(1, { message })\n}\n\nconst hexColorSchema = z.string().regex(/^#([0-9a-fA-F]{6})$/, {\n message: 'checkout.validation.common.invalidColor',\n})\nconst currencyCodeSchema = z.string().trim().toUpperCase().regex(/^[A-Z]{3}$/, {\n message: 'checkout.validation.common.invalidCurrencyCode',\n})\nconst optionalTrimmedString = z.preprocess(\n normalizeBlankString,\n z.string().trim().min(1, { message: 'checkout.validation.common.required' }).optional().nullable(),\n).optional()\nconst optionalUrlSchema = z.preprocess(\n normalizeBlankString,\n z.string().url('checkout.validation.common.invalidUrl').optional().nullable(),\n).optional()\nconst optionalFieldsetCodeSchema = z.preprocess(\n normalizeBlankString,\n z.string().regex(fieldsetCodeRegex, {\n message: 'checkout.validation.common.invalidFieldsetCode',\n }).optional().nullable(),\n).optional()\nconst positiveMoneySchema = z.coerce.number().finite('checkout.validation.common.invalidNumber').nonnegative('checkout.validation.common.nonNegativeNumber')\nconst linkStatusSchema = z.enum(CHECKOUT_LINK_STATUSES)\n\nexport const customerFieldOptionSchema = z.object({\n value: requiredTrimmedString('checkout.validation.common.required'),\n label: requiredTrimmedString('checkout.validation.common.required'),\n})\n\nexport const customerFieldDefinitionSchema = z.object({\n key: z.string().regex(/^[a-z][A-Za-z0-9]*$/, {\n message: 'checkout.validation.customerFields.key.invalid',\n }),\n label: requiredTrimmedString('checkout.validation.common.required'),\n kind: z.enum(['text', 'multiline', 'boolean', 'select', 'radio']),\n required: z.boolean(),\n fixed: z.boolean(),\n placeholder: optionalTrimmedString,\n options: z.array(customerFieldOptionSchema).optional(),\n sortOrder: z.coerce.number().int('checkout.validation.common.integer').min(0, {\n message: 'checkout.validation.common.nonNegativeInteger',\n }),\n})\n\nexport const legalDocumentSchema = z.preprocess(\n normalizeOptionalDocument,\n z.object({\n title: requiredTrimmedString('checkout.validation.common.required'),\n markdown: requiredTrimmedString('checkout.validation.common.required'),\n required: z.boolean().default(false),\n }).optional(),\n)\n\nexport const legalDocumentsSchema = z.object({\n terms: legalDocumentSchema.optional(),\n privacyPolicy: legalDocumentSchema.optional(),\n}).optional()\n\nexport const priceListItemSchema = z.object({\n id: requiredTrimmedString('checkout.validation.common.required'),\n description: requiredTrimmedString('checkout.validation.common.required'),\n amount: positiveMoneySchema,\n currencyCode: currencyCodeSchema,\n})\n\nexport const gatewaySettingsSchema = z.record(z.string(), z.unknown()).optional()\n\nconst checkoutContentSchema = z.object({\n name: requiredTrimmedString('checkout.validation.name.required'),\n title: optionalTrimmedString,\n subtitle: optionalTrimmedString,\n description: z.string().optional().nullable(),\n logoAttachmentId: z.string().uuid('checkout.validation.common.invalidUuid').optional().nullable(),\n logoUrl: optionalUrlSchema,\n primaryColor: hexColorSchema.optional().nullable(),\n secondaryColor: hexColorSchema.optional().nullable(),\n backgroundColor: hexColorSchema.optional().nullable(),\n themeMode: z.enum(['light', 'dark', 'auto']).default('auto'),\n pricingMode: z.enum(['fixed', 'custom_amount', 'price_list']),\n fixedPriceAmount: positiveMoneySchema.optional().nullable(),\n fixedPriceCurrencyCode: currencyCodeSchema.optional().nullable(),\n fixedPriceIncludesTax: z.boolean().default(true),\n fixedPriceOriginalAmount: positiveMoneySchema.optional().nullable(),\n customAmountMin: positiveMoneySchema.optional().nullable(),\n customAmountMax: positiveMoneySchema.optional().nullable(),\n customAmountCurrencyCode: currencyCodeSchema.optional().nullable(),\n priceListItems: z.array(priceListItemSchema).optional().nullable(),\n gatewayProviderKey: requiredTrimmedString('checkout.validation.gatewayProviderKey.required'),\n gatewaySettings: gatewaySettingsSchema,\n customFieldsetCode: optionalFieldsetCodeSchema,\n collectCustomerDetails: z.boolean().default(true),\n customerFieldsSchema: z.array(customerFieldDefinitionSchema).default([...DEFAULT_CHECKOUT_CUSTOMER_FIELDS]),\n legalDocuments: legalDocumentsSchema,\n displayCustomFieldsOnPage: z.boolean().default(false),\n successTitle: optionalTrimmedString,\n successMessage: z.string().optional().nullable(),\n cancelTitle: optionalTrimmedString,\n cancelMessage: z.string().optional().nullable(),\n errorTitle: optionalTrimmedString,\n errorMessage: z.string().optional().nullable(),\n successEmailSubject: optionalTrimmedString,\n successEmailBody: z.string().optional().nullable(),\n sendSuccessEmail: z.boolean().default(true),\n errorEmailSubject: optionalTrimmedString,\n errorEmailBody: z.string().optional().nullable(),\n sendErrorEmail: z.boolean().default(true),\n startEmailSubject: optionalTrimmedString,\n startEmailBody: z.string().optional().nullable(),\n sendStartEmail: z.boolean().default(true),\n password: optionalTrimmedString,\n maxCompletions: z.coerce.number().int('checkout.validation.common.integer').positive('checkout.validation.common.positiveInteger').optional().nullable(),\n status: linkStatusSchema.default('draft'),\n checkoutType: z.enum(['pay_link', 'simple_checkout']).default('pay_link'),\n})\n\nfunction validatePricingConsistency<T extends z.infer<typeof checkoutContentSchema>>(value: T, ctx: z.RefinementCtx) {\n if (value.pricingMode === 'fixed') {\n if (value.fixedPriceAmount == null) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'checkout.validation.fixedPriceAmount.required', path: ['fixedPriceAmount'] })\n }\n if (!value.fixedPriceCurrencyCode) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'checkout.validation.fixedPriceCurrencyCode.required', path: ['fixedPriceCurrencyCode'] })\n }\n }\n\n if (value.pricingMode === 'custom_amount') {\n if (value.customAmountMin == null) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'checkout.validation.customAmountMin.required', path: ['customAmountMin'] })\n }\n if (value.customAmountMax == null) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'checkout.validation.customAmountMax.required', path: ['customAmountMax'] })\n }\n if (!value.customAmountCurrencyCode) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'checkout.validation.customAmountCurrencyCode.required', path: ['customAmountCurrencyCode'] })\n }\n if (value.customAmountMin != null && value.customAmountMax != null && value.customAmountMin > value.customAmountMax) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'checkout.validation.customAmount.range', path: ['customAmountMax'] })\n }\n }\n\n if (value.pricingMode === 'price_list') {\n if (!Array.isArray(value.priceListItems) || value.priceListItems.length === 0) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'checkout.validation.priceListItems.required', path: ['priceListItems'] })\n return\n }\n const currencies = new Set(value.priceListItems.map((item) => item.currencyCode))\n if (currencies.size > 1) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'checkout.validation.priceListItems.singleCurrency', path: ['priceListItems'] })\n }\n }\n}\n\nexport const createTemplateSchema = checkoutContentSchema.superRefine(validatePricingConsistency)\n\nfunction applyPartialPricingConsistency(value: Record<string, unknown>, ctx: z.RefinementCtx) {\n if (!value.pricingMode) return\n validatePricingConsistency({\n ...checkoutContentSchema.parse({\n ...value,\n name: value.name ?? 'placeholder',\n pricingMode: value.pricingMode,\n customerFieldsSchema: value.customerFieldsSchema ?? [...DEFAULT_CHECKOUT_CUSTOMER_FIELDS],\n }),\n ...value,\n }, ctx)\n}\n\nexport const updateTemplateSchema = checkoutContentSchema.partial().extend({\n id: z.string().uuid('checkout.validation.common.invalidUuid'),\n password: optionalTrimmedString,\n customerFieldsSchema: z.array(customerFieldDefinitionSchema).optional(),\n}).superRefine((value, ctx) => {\n applyPartialPricingConsistency(value, ctx)\n})\n\nexport const createLinkSchema = createTemplateSchema.safeExtend({\n templateId: z.string().uuid('checkout.validation.common.invalidUuid').optional().nullable(),\n slug: optionalTrimmedString,\n})\n\nexport const updateLinkSchema = checkoutContentSchema.partial().safeExtend({\n id: z.string().uuid('checkout.validation.common.invalidUuid'),\n templateId: z.string().uuid('checkout.validation.common.invalidUuid').optional().nullable(),\n slug: optionalTrimmedString,\n password: optionalTrimmedString,\n customerFieldsSchema: z.array(customerFieldDefinitionSchema).optional(),\n}).superRefine((value, ctx) => {\n applyPartialPricingConsistency(value, ctx)\n})\n\nexport const transactionStatusSchema = z.enum(['pending', 'processing', 'completed', 'failed', 'cancelled', 'expired'])\n\nexport const transactionCreateSchema = z.object({\n linkId: z.string().uuid('checkout.validation.common.invalidUuid'),\n amount: positiveMoneySchema,\n currencyCode: currencyCodeSchema,\n idempotencyKey: requiredTrimmedString('checkout.validation.common.required'),\n customerData: z.record(z.string(), z.unknown()).default({}),\n firstName: optionalTrimmedString,\n lastName: optionalTrimmedString,\n email: optionalTrimmedString,\n phone: optionalTrimmedString,\n gatewayTransactionId: z.string().uuid('checkout.validation.common.invalidUuid').optional().nullable(),\n paymentStatus: optionalTrimmedString,\n selectedPriceItemId: optionalTrimmedString,\n acceptedLegalConsents: z.record(z.string(), z.unknown()).optional().nullable(),\n ipAddress: optionalTrimmedString,\n userAgent: z.string().optional().nullable(),\n tenantId: z.string().uuid('checkout.validation.common.invalidUuid'),\n organizationId: z.string().uuid('checkout.validation.common.invalidUuid'),\n})\n\nexport const transactionUpdateStatusSchema = z.object({\n id: z.string().uuid('checkout.validation.common.invalidUuid'),\n status: transactionStatusSchema,\n paymentStatus: optionalTrimmedString,\n gatewayTransactionId: z.string().uuid('checkout.validation.common.invalidUuid').optional().nullable(),\n tenantId: z.string().uuid('checkout.validation.common.invalidUuid'),\n organizationId: z.string().uuid('checkout.validation.common.invalidUuid'),\n})\n\nexport const publicPasswordVerifySchema = z.object({\n password: z.string().min(1, { message: 'checkout.validation.common.required' }),\n})\n\nexport const publicSubmitSchema = z.object({\n customerData: z.record(z.string(), z.unknown()),\n acceptedLegalConsents: z.object({\n terms: z.boolean().optional(),\n privacyPolicy: z.boolean().optional(),\n }).default({}),\n amount: z.coerce.number().finite().nonnegative().optional(),\n selectedPriceItemId: optionalTrimmedString,\n})\n\nexport type CustomerFieldDefinitionInput = z.infer<typeof customerFieldDefinitionSchema>\nexport type PriceListItemInput = z.infer<typeof priceListItemSchema>\nexport type CreateTemplateInput = z.infer<typeof createTemplateSchema>\nexport type UpdateTemplateInput = z.infer<typeof updateTemplateSchema>\nexport type CreateLinkInput = z.infer<typeof createLinkSchema>\nexport type UpdateLinkInput = z.infer<typeof updateLinkSchema>\nexport type CreateTransactionInput = z.infer<typeof transactionCreateSchema>\nexport type UpdateTransactionStatusInput = z.infer<typeof transactionUpdateStatusSchema>\nexport type PublicSubmitInput = z.infer<typeof publicSubmitSchema>\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { z } from 'zod'\nimport { fieldsetCodeRegex } from '@open-mercato/shared/modules/entities/validators'\nimport { DEFAULT_CHECKOUT_CUSTOMER_FIELDS } from '../lib/defaults'\nimport { CHECKOUT_LINK_STATUSES } from '../lib/constants'\n\nfunction normalizeBlankString(value: unknown): unknown {\n if (typeof value !== 'string') return value\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : null\n}\n\nfunction normalizeOptionalDocument(value: unknown): unknown {\n if (!value || typeof value !== 'object' || Array.isArray(value)) return value\n const source = value as Record<string, unknown>\n const title = typeof source.title === 'string' ? source.title.trim() : ''\n const markdown = typeof source.markdown === 'string' ? source.markdown.trim() : ''\n const required = source.required === true\n if (!title && !markdown && !required) return undefined\n return value\n}\n\nfunction requiredTrimmedString(message: string) {\n return z.string().trim().min(1, { message })\n}\n\nconst hexColorSchema = z.string().regex(/^#([0-9a-fA-F]{6})$/, {\n message: 'checkout.validation.common.invalidColor',\n})\nconst currencyCodeSchema = z.string().trim().toUpperCase().regex(/^[A-Z]{3}$/, {\n message: 'checkout.validation.common.invalidCurrencyCode',\n})\nconst optionalTrimmedString = z.union([z.string(), z.null(), z.undefined()])\n .transform(normalizeBlankString)\n .pipe(z.string().trim().min(1, { message: 'checkout.validation.common.required' }).optional().nullable())\nconst optionalUrlSchema = z.union([z.string(), z.null(), z.undefined()])\n .transform(normalizeBlankString)\n .pipe(z.string().url('checkout.validation.common.invalidUrl').optional().nullable())\nconst optionalFieldsetCodeSchema = z.union([z.string(), z.null(), z.undefined()])\n .transform(normalizeBlankString)\n .pipe(z.string().regex(fieldsetCodeRegex, {\n message: 'checkout.validation.common.invalidFieldsetCode',\n }).optional().nullable())\nconst positiveMoneySchema = z.coerce.number().finite('checkout.validation.common.invalidNumber').nonnegative('checkout.validation.common.nonNegativeNumber')\nconst linkStatusSchema = z.enum(CHECKOUT_LINK_STATUSES)\n\nexport const customerFieldOptionSchema = z.object({\n value: requiredTrimmedString('checkout.validation.common.required'),\n label: requiredTrimmedString('checkout.validation.common.required'),\n})\n\nexport const customerFieldDefinitionSchema = z.object({\n key: z.string().regex(/^[a-z][A-Za-z0-9]*$/, {\n message: 'checkout.validation.customerFields.key.invalid',\n }),\n label: requiredTrimmedString('checkout.validation.common.required'),\n kind: z.enum(['text', 'multiline', 'boolean', 'select', 'radio']),\n required: z.boolean(),\n fixed: z.boolean(),\n placeholder: optionalTrimmedString,\n options: z.array(customerFieldOptionSchema).optional(),\n sortOrder: z.coerce.number().int('checkout.validation.common.integer').min(0, {\n message: 'checkout.validation.common.nonNegativeInteger',\n }),\n})\n\nexport const legalDocumentSchema = z.preprocess(\n normalizeOptionalDocument,\n z.object({\n title: requiredTrimmedString('checkout.validation.common.required'),\n markdown: requiredTrimmedString('checkout.validation.common.required'),\n required: z.boolean().default(false),\n }).optional(),\n)\n\nexport const legalDocumentsSchema = z.object({\n terms: legalDocumentSchema.optional(),\n privacyPolicy: legalDocumentSchema.optional(),\n}).optional()\n\nexport const priceListItemSchema = z.object({\n id: requiredTrimmedString('checkout.validation.common.required'),\n description: requiredTrimmedString('checkout.validation.common.required'),\n amount: positiveMoneySchema,\n currencyCode: currencyCodeSchema,\n})\n\nexport const gatewaySettingsSchema = z.record(z.string(), z.unknown()).optional()\n\nconst checkoutContentSchema = z.object({\n name: requiredTrimmedString('checkout.validation.name.required'),\n title: optionalTrimmedString,\n subtitle: optionalTrimmedString,\n description: z.string().optional().nullable(),\n logoAttachmentId: z.string().uuid('checkout.validation.common.invalidUuid').optional().nullable(),\n logoUrl: optionalUrlSchema,\n primaryColor: hexColorSchema.optional().nullable(),\n secondaryColor: hexColorSchema.optional().nullable(),\n backgroundColor: hexColorSchema.optional().nullable(),\n themeMode: z.enum(['light', 'dark', 'auto']).default('auto'),\n pricingMode: z.enum(['fixed', 'custom_amount', 'price_list']),\n fixedPriceAmount: positiveMoneySchema.optional().nullable(),\n fixedPriceCurrencyCode: currencyCodeSchema.optional().nullable(),\n fixedPriceIncludesTax: z.boolean().default(true),\n fixedPriceOriginalAmount: positiveMoneySchema.optional().nullable(),\n customAmountMin: positiveMoneySchema.optional().nullable(),\n customAmountMax: positiveMoneySchema.optional().nullable(),\n customAmountCurrencyCode: currencyCodeSchema.optional().nullable(),\n priceListItems: z.array(priceListItemSchema).optional().nullable(),\n gatewayProviderKey: requiredTrimmedString('checkout.validation.gatewayProviderKey.required'),\n gatewaySettings: gatewaySettingsSchema,\n customFieldsetCode: optionalFieldsetCodeSchema,\n collectCustomerDetails: z.boolean().default(true),\n customerFieldsSchema: z.array(customerFieldDefinitionSchema).default([...DEFAULT_CHECKOUT_CUSTOMER_FIELDS]),\n legalDocuments: legalDocumentsSchema,\n displayCustomFieldsOnPage: z.boolean().default(false),\n successTitle: optionalTrimmedString,\n successMessage: z.string().optional().nullable(),\n cancelTitle: optionalTrimmedString,\n cancelMessage: z.string().optional().nullable(),\n errorTitle: optionalTrimmedString,\n errorMessage: z.string().optional().nullable(),\n successEmailSubject: optionalTrimmedString,\n successEmailBody: z.string().optional().nullable(),\n sendSuccessEmail: z.boolean().default(true),\n errorEmailSubject: optionalTrimmedString,\n errorEmailBody: z.string().optional().nullable(),\n sendErrorEmail: z.boolean().default(true),\n startEmailSubject: optionalTrimmedString,\n startEmailBody: z.string().optional().nullable(),\n sendStartEmail: z.boolean().default(true),\n password: optionalTrimmedString,\n maxCompletions: z.coerce.number().int('checkout.validation.common.integer').positive('checkout.validation.common.positiveInteger').optional().nullable(),\n status: linkStatusSchema.default('draft'),\n checkoutType: z.enum(['pay_link', 'simple_checkout']).default('pay_link'),\n})\n\nfunction validatePricingConsistency<T extends z.infer<typeof checkoutContentSchema>>(value: T, ctx: z.RefinementCtx) {\n if (value.pricingMode === 'fixed') {\n if (value.fixedPriceAmount == null) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'checkout.validation.fixedPriceAmount.required', path: ['fixedPriceAmount'] })\n }\n if (!value.fixedPriceCurrencyCode) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'checkout.validation.fixedPriceCurrencyCode.required', path: ['fixedPriceCurrencyCode'] })\n }\n }\n\n if (value.pricingMode === 'custom_amount') {\n if (value.customAmountMin == null) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'checkout.validation.customAmountMin.required', path: ['customAmountMin'] })\n }\n if (value.customAmountMax == null) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'checkout.validation.customAmountMax.required', path: ['customAmountMax'] })\n }\n if (!value.customAmountCurrencyCode) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'checkout.validation.customAmountCurrencyCode.required', path: ['customAmountCurrencyCode'] })\n }\n if (value.customAmountMin != null && value.customAmountMax != null && value.customAmountMin > value.customAmountMax) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'checkout.validation.customAmount.range', path: ['customAmountMax'] })\n }\n }\n\n if (value.pricingMode === 'price_list') {\n if (!Array.isArray(value.priceListItems) || value.priceListItems.length === 0) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'checkout.validation.priceListItems.required', path: ['priceListItems'] })\n return\n }\n const currencies = new Set(value.priceListItems.map((item) => item.currencyCode))\n if (currencies.size > 1) {\n ctx.addIssue({ code: z.ZodIssueCode.custom, message: 'checkout.validation.priceListItems.singleCurrency', path: ['priceListItems'] })\n }\n }\n}\n\nexport const createTemplateSchema = checkoutContentSchema.superRefine(validatePricingConsistency)\n\nfunction applyPartialPricingConsistency(value: Record<string, unknown>, ctx: z.RefinementCtx) {\n if (!value.pricingMode) return\n validatePricingConsistency({\n ...checkoutContentSchema.parse({\n ...value,\n name: value.name ?? 'placeholder',\n pricingMode: value.pricingMode,\n customerFieldsSchema: value.customerFieldsSchema ?? [...DEFAULT_CHECKOUT_CUSTOMER_FIELDS],\n }),\n ...value,\n }, ctx)\n}\n\nexport const updateTemplateSchema = checkoutContentSchema.partial().extend({\n id: z.string().uuid('checkout.validation.common.invalidUuid'),\n password: optionalTrimmedString,\n customerFieldsSchema: z.array(customerFieldDefinitionSchema).optional(),\n}).superRefine((value, ctx) => {\n applyPartialPricingConsistency(value, ctx)\n})\n\nexport const createLinkSchema = createTemplateSchema.safeExtend({\n templateId: z.string().uuid('checkout.validation.common.invalidUuid').optional().nullable(),\n slug: optionalTrimmedString,\n})\n\nexport const updateLinkSchema = checkoutContentSchema.partial().safeExtend({\n id: z.string().uuid('checkout.validation.common.invalidUuid'),\n templateId: z.string().uuid('checkout.validation.common.invalidUuid').optional().nullable(),\n slug: optionalTrimmedString,\n password: optionalTrimmedString,\n customerFieldsSchema: z.array(customerFieldDefinitionSchema).optional(),\n}).superRefine((value, ctx) => {\n applyPartialPricingConsistency(value, ctx)\n})\n\nexport const transactionStatusSchema = z.enum(['pending', 'processing', 'completed', 'failed', 'cancelled', 'expired'])\n\nexport const transactionCreateSchema = z.object({\n linkId: z.string().uuid('checkout.validation.common.invalidUuid'),\n amount: positiveMoneySchema,\n currencyCode: currencyCodeSchema,\n idempotencyKey: requiredTrimmedString('checkout.validation.common.required'),\n customerData: z.record(z.string(), z.unknown()).default({}),\n firstName: optionalTrimmedString,\n lastName: optionalTrimmedString,\n email: optionalTrimmedString,\n phone: optionalTrimmedString,\n gatewayTransactionId: z.string().uuid('checkout.validation.common.invalidUuid').optional().nullable(),\n paymentStatus: optionalTrimmedString,\n selectedPriceItemId: optionalTrimmedString,\n acceptedLegalConsents: z.record(z.string(), z.unknown()).optional().nullable(),\n ipAddress: optionalTrimmedString,\n userAgent: z.string().optional().nullable(),\n tenantId: z.string().uuid('checkout.validation.common.invalidUuid'),\n organizationId: z.string().uuid('checkout.validation.common.invalidUuid'),\n})\n\nexport const transactionUpdateStatusSchema = z.object({\n id: z.string().uuid('checkout.validation.common.invalidUuid'),\n status: transactionStatusSchema,\n paymentStatus: optionalTrimmedString,\n gatewayTransactionId: z.string().uuid('checkout.validation.common.invalidUuid').optional().nullable(),\n tenantId: z.string().uuid('checkout.validation.common.invalidUuid'),\n organizationId: z.string().uuid('checkout.validation.common.invalidUuid'),\n})\n\nexport const publicPasswordVerifySchema = z.object({\n password: z.string().min(1, { message: 'checkout.validation.common.required' }),\n})\n\nexport const publicSubmitSchema = z.object({\n customerData: z.record(z.string(), z.unknown()),\n acceptedLegalConsents: z.object({\n terms: z.boolean().optional(),\n privacyPolicy: z.boolean().optional(),\n }).default({}),\n amount: z.coerce.number().finite().nonnegative().optional(),\n selectedPriceItemId: optionalTrimmedString,\n})\n\nexport type CustomerFieldDefinitionInput = z.infer<typeof customerFieldDefinitionSchema>\nexport type PriceListItemInput = z.infer<typeof priceListItemSchema>\nexport type CreateTemplateInput = z.infer<typeof createTemplateSchema>\nexport type UpdateTemplateInput = z.infer<typeof updateTemplateSchema>\nexport type CreateLinkInput = z.infer<typeof createLinkSchema>\nexport type UpdateLinkInput = z.infer<typeof updateLinkSchema>\nexport type CreateTransactionInput = z.infer<typeof transactionCreateSchema>\nexport type UpdateTransactionStatusInput = z.infer<typeof transactionUpdateStatusSchema>\nexport type PublicSubmitInput = z.infer<typeof publicSubmitSchema>\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/checkout",
3
- "version": "0.6.1-develop.3054.g0367114684",
3
+ "version": "0.6.1-develop.3060.d6cca7ade1",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -61,17 +61,17 @@
61
61
  }
62
62
  },
63
63
  "dependencies": {
64
- "@open-mercato/core": "0.6.1-develop.3054.g0367114684",
65
- "@open-mercato/ui": "0.6.1-develop.3054.g0367114684",
64
+ "@open-mercato/core": "0.6.1-develop.3060.d6cca7ade1",
65
+ "@open-mercato/ui": "0.6.1-develop.3060.d6cca7ade1",
66
66
  "bcryptjs": "^3.0.3"
67
67
  },
68
68
  "peerDependencies": {
69
69
  "@mikro-orm/postgresql": "^7.0.13",
70
- "@open-mercato/shared": "0.6.1-develop.3054.g0367114684",
70
+ "@open-mercato/shared": "0.6.1-develop.3060.d6cca7ade1",
71
71
  "react": "^19.0.0"
72
72
  },
73
73
  "devDependencies": {
74
- "@open-mercato/shared": "0.6.1-develop.3054.g0367114684",
74
+ "@open-mercato/shared": "0.6.1-develop.3060.d6cca7ade1",
75
75
  "@types/jest": "^30.0.0",
76
76
  "esbuild": "^0.28.0",
77
77
  "glob": "^13.0.6",
@@ -194,7 +194,10 @@ export async function createTemplateFixture(
194
194
  data: input,
195
195
  })
196
196
  const body = await readJsonSafe<{ id?: string }>(response)
197
- expect(response.ok(), `Failed to create template: ${response.status()}`).toBeTruthy()
197
+ expect(
198
+ response.ok(),
199
+ `Failed to create template: ${response.status()} ${JSON.stringify(body)}`,
200
+ ).toBeTruthy()
198
201
  expect(typeof body?.id === 'string' && body.id.length > 0, 'Template id is required').toBeTruthy()
199
202
  return body!.id!
200
203
  }
@@ -209,7 +212,10 @@ export async function createLinkFixture(
209
212
  data: input,
210
213
  })
211
214
  const body = await readJsonSafe<{ id?: string; slug?: string }>(response)
212
- expect(response.ok(), `Failed to create link: ${response.status()}`).toBeTruthy()
215
+ expect(
216
+ response.ok(),
217
+ `Failed to create link: ${response.status()} ${JSON.stringify(body)}`,
218
+ ).toBeTruthy()
213
219
  expect(typeof body?.id === 'string' && body.id.length > 0, 'Link id is required').toBeTruthy()
214
220
  expect(typeof body?.slug === 'string' && body.slug.length > 0, 'Link slug is required').toBeTruthy()
215
221
  return { id: body!.id!, slug: body!.slug! }
@@ -0,0 +1,32 @@
1
+ import { createLinkSchema, createTemplateSchema } from '../validators'
2
+
3
+ describe('checkout validators', () => {
4
+ test('createTemplateSchema accepts payloads that omit optional normalized fields', () => {
5
+ const result = createTemplateSchema.parse({
6
+ name: 'QA template',
7
+ pricingMode: 'fixed',
8
+ fixedPriceAmount: 49.99,
9
+ fixedPriceCurrencyCode: 'USD',
10
+ gatewayProviderKey: 'mock',
11
+ })
12
+
13
+ expect(result.logoUrl).toBeUndefined()
14
+ expect(result.customFieldsetCode).toBeUndefined()
15
+ expect(result.successTitle).toBeUndefined()
16
+ expect(result.password).toBeUndefined()
17
+ })
18
+
19
+ test('createLinkSchema accepts payloads that omit optional normalized fields including slug', () => {
20
+ const result = createLinkSchema.parse({
21
+ name: 'QA link',
22
+ pricingMode: 'fixed',
23
+ fixedPriceAmount: 49.99,
24
+ fixedPriceCurrencyCode: 'USD',
25
+ gatewayProviderKey: 'mock',
26
+ })
27
+
28
+ expect(result.logoUrl).toBeUndefined()
29
+ expect(result.slug).toBeUndefined()
30
+ expect(result.password).toBeUndefined()
31
+ })
32
+ })
@@ -29,20 +29,17 @@ const hexColorSchema = z.string().regex(/^#([0-9a-fA-F]{6})$/, {
29
29
  const currencyCodeSchema = z.string().trim().toUpperCase().regex(/^[A-Z]{3}$/, {
30
30
  message: 'checkout.validation.common.invalidCurrencyCode',
31
31
  })
32
- const optionalTrimmedString = z.preprocess(
33
- normalizeBlankString,
34
- z.string().trim().min(1, { message: 'checkout.validation.common.required' }).optional().nullable(),
35
- ).optional()
36
- const optionalUrlSchema = z.preprocess(
37
- normalizeBlankString,
38
- z.string().url('checkout.validation.common.invalidUrl').optional().nullable(),
39
- ).optional()
40
- const optionalFieldsetCodeSchema = z.preprocess(
41
- normalizeBlankString,
42
- z.string().regex(fieldsetCodeRegex, {
32
+ const optionalTrimmedString = z.union([z.string(), z.null(), z.undefined()])
33
+ .transform(normalizeBlankString)
34
+ .pipe(z.string().trim().min(1, { message: 'checkout.validation.common.required' }).optional().nullable())
35
+ const optionalUrlSchema = z.union([z.string(), z.null(), z.undefined()])
36
+ .transform(normalizeBlankString)
37
+ .pipe(z.string().url('checkout.validation.common.invalidUrl').optional().nullable())
38
+ const optionalFieldsetCodeSchema = z.union([z.string(), z.null(), z.undefined()])
39
+ .transform(normalizeBlankString)
40
+ .pipe(z.string().regex(fieldsetCodeRegex, {
43
41
  message: 'checkout.validation.common.invalidFieldsetCode',
44
- }).optional().nullable(),
45
- ).optional()
42
+ }).optional().nullable())
46
43
  const positiveMoneySchema = z.coerce.number().finite('checkout.validation.common.invalidNumber').nonnegative('checkout.validation.common.nonNegativeNumber')
47
44
  const linkStatusSchema = z.enum(CHECKOUT_LINK_STATUSES)
48
45