@open-mercato/core 0.4.9-develop-e55592929f → 0.4.9-develop-97d4cca067

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.
Files changed (86) hide show
  1. package/dist/helpers/integration/api.js +66 -0
  2. package/dist/helpers/integration/api.js.map +7 -0
  3. package/dist/helpers/integration/apiKeysFixtures.js +16 -0
  4. package/dist/helpers/integration/apiKeysFixtures.js.map +7 -0
  5. package/dist/helpers/integration/attachmentsFixtures.js +61 -0
  6. package/dist/helpers/integration/attachmentsFixtures.js.map +7 -0
  7. package/dist/helpers/integration/auth.js +190 -0
  8. package/dist/helpers/integration/auth.js.map +7 -0
  9. package/dist/helpers/integration/authFixtures.js +39 -0
  10. package/dist/helpers/integration/authFixtures.js.map +7 -0
  11. package/dist/helpers/integration/authUi.js +31 -0
  12. package/dist/helpers/integration/authUi.js.map +7 -0
  13. package/dist/helpers/integration/businessRulesFixtures.js +40 -0
  14. package/dist/helpers/integration/businessRulesFixtures.js.map +7 -0
  15. package/dist/helpers/integration/catalogFixtures.js +49 -0
  16. package/dist/helpers/integration/catalogFixtures.js.map +7 -0
  17. package/dist/helpers/integration/crmFixtures.js +91 -0
  18. package/dist/helpers/integration/crmFixtures.js.map +7 -0
  19. package/dist/helpers/integration/currenciesFixtures.js +39 -0
  20. package/dist/helpers/integration/currenciesFixtures.js.map +7 -0
  21. package/dist/helpers/integration/dictionariesFixtures.js +16 -0
  22. package/dist/helpers/integration/dictionariesFixtures.js.map +7 -0
  23. package/dist/helpers/integration/featureTogglesFixtures.js +23 -0
  24. package/dist/helpers/integration/featureTogglesFixtures.js.map +7 -0
  25. package/dist/helpers/integration/generalFixtures.js +56 -0
  26. package/dist/helpers/integration/generalFixtures.js.map +7 -0
  27. package/dist/helpers/integration/inboxFixtures.js +67 -0
  28. package/dist/helpers/integration/inboxFixtures.js.map +7 -0
  29. package/dist/helpers/integration/notificationsFixtures.js +48 -0
  30. package/dist/helpers/integration/notificationsFixtures.js.map +7 -0
  31. package/dist/helpers/integration/salesFixtures.js +63 -0
  32. package/dist/helpers/integration/salesFixtures.js.map +7 -0
  33. package/dist/helpers/integration/salesUi.js +827 -0
  34. package/dist/helpers/integration/salesUi.js.map +7 -0
  35. package/dist/helpers/integration/sseEventCollector.js +27 -0
  36. package/dist/helpers/integration/sseEventCollector.js.map +7 -0
  37. package/dist/helpers/integration/staffFixtures.js +47 -0
  38. package/dist/helpers/integration/staffFixtures.js.map +7 -0
  39. package/dist/modules/auth/lib/setup-app.js +17 -1
  40. package/dist/modules/auth/lib/setup-app.js.map +2 -2
  41. package/dist/testing/integration/api.js +2 -0
  42. package/dist/testing/integration/api.js.map +7 -0
  43. package/dist/testing/integration/auth.js +2 -0
  44. package/dist/testing/integration/auth.js.map +7 -0
  45. package/dist/testing/integration/authFixtures.js +2 -0
  46. package/dist/testing/integration/authFixtures.js.map +7 -0
  47. package/dist/testing/integration/authUi.js +2 -0
  48. package/dist/testing/integration/authUi.js.map +7 -0
  49. package/dist/testing/integration/crmFixtures.js +2 -0
  50. package/dist/testing/integration/crmFixtures.js.map +7 -0
  51. package/dist/testing/integration/dictionariesFixtures.js +2 -0
  52. package/dist/testing/integration/dictionariesFixtures.js.map +7 -0
  53. package/dist/testing/integration/generalFixtures.js +2 -0
  54. package/dist/testing/integration/generalFixtures.js.map +7 -0
  55. package/dist/testing/integration/index.js +48 -0
  56. package/dist/testing/integration/index.js.map +7 -0
  57. package/package.json +11 -3
  58. package/src/helpers/integration/api.ts +87 -0
  59. package/src/helpers/integration/apiKeysFixtures.ts +17 -0
  60. package/src/helpers/integration/attachmentsFixtures.ts +114 -0
  61. package/src/helpers/integration/auth.ts +208 -0
  62. package/src/helpers/integration/authFixtures.ts +52 -0
  63. package/src/helpers/integration/authUi.ts +33 -0
  64. package/src/helpers/integration/businessRulesFixtures.ts +53 -0
  65. package/src/helpers/integration/catalogFixtures.ts +73 -0
  66. package/src/helpers/integration/crmFixtures.ts +132 -0
  67. package/src/helpers/integration/currenciesFixtures.ts +49 -0
  68. package/src/helpers/integration/dictionariesFixtures.ts +17 -0
  69. package/src/helpers/integration/featureTogglesFixtures.ts +28 -0
  70. package/src/helpers/integration/generalFixtures.ts +71 -0
  71. package/src/helpers/integration/inboxFixtures.ts +94 -0
  72. package/src/helpers/integration/notificationsFixtures.ts +67 -0
  73. package/src/helpers/integration/salesFixtures.ts +89 -0
  74. package/src/helpers/integration/salesUi.ts +936 -0
  75. package/src/helpers/integration/sseEventCollector.ts +30 -0
  76. package/src/helpers/integration/staffFixtures.ts +61 -0
  77. package/src/modules/auth/lib/setup-app.ts +22 -0
  78. package/src/testing/integration/api.ts +1 -0
  79. package/src/testing/integration/auth.ts +1 -0
  80. package/src/testing/integration/authFixtures.ts +1 -0
  81. package/src/testing/integration/authUi.ts +1 -0
  82. package/src/testing/integration/crmFixtures.ts +1 -0
  83. package/src/testing/integration/dictionariesFixtures.ts +1 -0
  84. package/src/testing/integration/generalFixtures.ts +1 -0
  85. package/src/testing/integration/index.ts +22 -0
  86. package/tsconfig.json +3 -0
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/helpers/integration/salesUi.ts"],
4
+ "sourcesContent": ["import { expect, type Locator, type Page } from '@playwright/test';\nimport { apiRequest, getAuthToken } from './api';\n\ntype DocumentKind = 'quote' | 'order';\n\ntype CreateDocumentOptions = {\n kind: DocumentKind;\n customerQuery?: string;\n channelQuery?: string;\n};\n\ntype ChannelListItem = {\n id?: string | null;\n name?: string | null;\n code?: string | null;\n isActive?: boolean | null;\n};\n\ntype AddLineOptions = {\n name: string;\n quantity: number;\n unitPriceGross: number;\n taxClassName?: string;\n};\n\ntype AddAdjustmentOptions = {\n label: string;\n kindLabel?: string;\n netAmount: number;\n};\n\nconst TEST_WAIT_TIMEOUT_MS = 10_000;\n\nfunction escapeRegExp(value: string): string {\n return value.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\$&');\n}\n\nfunction parseCurrencyAmount(value: string): number {\n const normalized = value.replace(/,/g, '');\n const matches = normalized.match(/-?\\$[0-9]+(?:\\.[0-9]{2})?/g);\n const lastMatch = matches?.[matches.length - 1];\n if (!lastMatch) {\n throw new Error(`Could not parse currency from: ${value}`);\n }\n return Number.parseFloat(lastMatch.replace('$', ''));\n}\n\nfunction normalizeAdjustmentKindValue(kindLabel: string): string {\n return kindLabel.trim().toLowerCase().replace(/\\s+/g, '_');\n}\n\nfunction readId(payload: unknown, keys: string[]): string | null {\n if (!payload || typeof payload !== 'object') return null;\n const map = payload as Record<string, unknown>;\n for (const key of keys) {\n const value = map[key];\n if (typeof value === 'string' && value.length > 0) return value;\n }\n for (const value of Object.values(map)) {\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n const nested = readId(value, keys);\n if (nested) return nested;\n }\n }\n return null;\n}\n\nasync function ensureSalesDocumentFixtures(\n page: Page,\n options: CreateDocumentOptions,\n): Promise<{ customerQuery: string; channelQuery: string }> {\n let customerQuery = options.customerQuery;\n let channelQuery = options.channelQuery;\n\n if (customerQuery && channelQuery) {\n return { customerQuery, channelQuery };\n }\n\n const token = await getAuthToken(page.request, 'admin').catch(() => null);\n if (!token) {\n if (!customerQuery) {\n customerQuery = `QA Sales Customer ${Date.now()}`;\n await page.goto('/backend/customers/companies/create');\n await page.locator('form').getByRole('textbox').first().fill(customerQuery);\n await page.getByPlaceholder('https://example.com').fill('https://example.com');\n await page.locator('form').getByRole('button', { name: /Create Company/i }).click();\n await expect(page).toHaveURL(/\\/backend\\/customers\\/companies\\/[0-9a-f-]{36}$/i);\n }\n if (!channelQuery) {\n const timestamp = Date.now();\n channelQuery = `QA Sales Channel ${timestamp}`;\n const channelCode = `qa-sales-channel-${timestamp}`;\n await page.goto('/backend/sales/channels');\n await page.getByRole('link', { name: /Add channel/i }).click();\n const createForm = page.locator('form').first();\n await createForm.getByRole('textbox').nth(0).fill(channelQuery);\n await createForm.getByRole('textbox').nth(1).fill(channelCode);\n await page.getByRole('button', { name: /Create channel|Create/i }).last().click();\n await expect(page).toHaveURL(/\\/backend\\/sales\\/channels$/i);\n }\n return {\n customerQuery,\n channelQuery,\n };\n }\n\n if (!customerQuery) {\n const companyName = `QA Sales Customer ${Date.now()}`;\n const companyResponse = await apiRequest(page.request, 'POST', '/api/customers/companies', {\n token,\n data: { displayName: companyName },\n }).catch(() => null);\n if (companyResponse && companyResponse.ok()) {\n const companyBody = (await companyResponse.json().catch(() => null)) as unknown;\n const companyId = readId(companyBody, ['id', 'entityId', 'companyId']);\n if (companyId) {\n await apiRequest(page.request, 'POST', '/api/customers/addresses', {\n token,\n data: {\n entityId: companyId,\n name: 'Primary',\n purpose: 'Shipping',\n addressLine1: '100 QA Street',\n city: 'Austin',\n postalCode: '78701',\n country: 'US',\n isPrimary: true,\n },\n }).catch(() => {});\n customerQuery = companyName;\n }\n }\n if (!customerQuery) {\n customerQuery = 'Copperleaf';\n }\n }\n\n if (!channelQuery) {\n const existingChannelsResponse = await apiRequest(\n page.request,\n 'GET',\n '/api/sales/channels?page=1&pageSize=20&isActive=true',\n { token },\n ).catch(() => null);\n const existingChannelsBody = (await existingChannelsResponse?.json().catch(() => null)) as { items?: ChannelListItem[] } | null;\n const existingChannels = Array.isArray(existingChannelsBody?.items) ? existingChannelsBody.items : [];\n const preferredExistingChannel =\n existingChannels.find((item) => item.code === 'online' && item.isActive !== false) ??\n existingChannels.find((item) => item.isActive !== false);\n if (preferredExistingChannel?.name) {\n channelQuery = preferredExistingChannel.name;\n } else {\n const timestamp = Date.now();\n const channelName = `QA Sales Channel ${timestamp}`;\n const channelCode = `qa-sales-channel-${timestamp}`;\n const channelResponse = await apiRequest(page.request, 'POST', '/api/sales/channels', {\n token,\n data: {\n name: channelName,\n code: channelCode,\n },\n }).catch(() => null);\n if (channelResponse && channelResponse.ok()) {\n channelQuery = channelName;\n } else {\n channelQuery = 'online';\n }\n }\n }\n\n return {\n customerQuery: customerQuery ?? 'Copperleaf',\n channelQuery: channelQuery ?? 'online',\n };\n}\n\nasync function selectFirstAddressIfAvailable(page: Page): Promise<void> {\n const addressSelect = page\n .locator('select')\n .filter({ has: page.locator('option', { hasText: 'Select address' }) })\n .first();\n if ((await addressSelect.count()) === 0) return;\n if (!(await addressSelect.isEnabled())) return;\n\n const nextValue = await addressSelect.evaluate((element) => {\n const select = element as HTMLSelectElement;\n return select.options.length > 1 ? select.options[1]?.value ?? null : null;\n });\n if (nextValue) {\n await addressSelect.selectOption(nextValue);\n }\n}\n\nasync function ensureShippingMethodFixture(page: Page): Promise<void> {\n const token = await getAuthToken(page.request, 'admin').catch(() => null);\n if (!token) return;\n\n const existing = await apiRequest(\n page.request,\n 'GET',\n '/api/sales/shipping-methods?page=1&pageSize=1&isActive=true',\n { token },\n ).catch(() => null);\n const existingBody = (await existing?.json().catch(() => null)) as { result?: { items?: unknown[] } } | null;\n const existingItems = Array.isArray(existingBody?.result?.items) ? existingBody?.result?.items : [];\n if (existingItems.length > 0) return;\n\n const stamp = Date.now();\n await apiRequest(page.request, 'POST', '/api/sales/shipping-methods', {\n token,\n data: {\n name: `QA Shipping Method ${stamp}`,\n code: `qa-shipping-${stamp}`,\n isActive: true,\n currencyCode: 'USD',\n baseRateNet: '10.00',\n baseRateGross: '10.00',\n },\n }).catch(() => {});\n}\n\nfunction lookupRootFromInput(input: Locator): Locator {\n return input.locator('xpath=ancestor::div[contains(@class,\"space-y-3\")][1]');\n}\n\nasync function waitForLookupIdle(root: Locator): Promise<void> {\n await root\n .getByText(/Searching\u2026|Searching\\.\\.\\.|Loading\u2026|Loading\\.\\.\\./i)\n .first()\n .waitFor({ state: 'hidden', timeout: 1_200 })\n .catch(() => {});\n}\n\nasync function waitForOptionalTextToDisappear(scope: Locator, pattern: RegExp, timeout = 2_500): Promise<void> {\n await scope.getByText(pattern).first().waitFor({ state: 'hidden', timeout }).catch(() => {});\n}\n\nasync function waitForStableVisibility(locator: Locator, timeout = TEST_WAIT_TIMEOUT_MS): Promise<void> {\n await expect(locator).toBeVisible({ timeout });\n let stableChecks = 0;\n const deadline = Date.now() + Math.min(timeout, 2_000);\n while (Date.now() < deadline) {\n if (await locator.isVisible().catch(() => false)) {\n stableChecks += 1;\n if (stableChecks >= 3) return;\n } else {\n stableChecks = 0;\n }\n await locator.page().waitForTimeout(50).catch(() => {});\n }\n}\n\nasync function waitForDialogFieldReady(\n dialog: Locator,\n field: Locator,\n loadingPattern?: RegExp,\n): Promise<void> {\n await expect(dialog).toBeVisible({ timeout: TEST_WAIT_TIMEOUT_MS });\n if (loadingPattern) {\n await waitForOptionalTextToDisappear(dialog, loadingPattern, TEST_WAIT_TIMEOUT_MS);\n }\n await waitForStableVisibility(field, TEST_WAIT_TIMEOUT_MS);\n await field.scrollIntoViewIfNeeded().catch(() => {});\n}\n\nasync function recoverGenericErrorPageIfPresent(page: Page): Promise<boolean> {\n const errorHeading = page.getByRole('heading', { name: /^Something went wrong$/i }).first();\n if (!(await errorHeading.isVisible().catch(() => false))) return false;\n const retryButton = page.getByRole('button', { name: /Try again/i }).first();\n if (await retryButton.isVisible().catch(() => false)) {\n await retryButton.click().catch(() => {});\n await page.waitForLoadState('domcontentloaded').catch(() => {});\n } else {\n await page.reload({ waitUntil: 'domcontentloaded' }).catch(() => {});\n }\n return true;\n}\n\nasync function resolveCustomerEntityId(\n page: Page,\n token: string,\n customerQuery: string,\n): Promise<string | null> {\n const params = new URLSearchParams({ page: '1', pageSize: '5', search: customerQuery });\n const response = await apiRequest(page.request, 'GET', `/api/customers/companies?${params.toString()}`, { token }).catch(() => null);\n const body = (await response?.json().catch(() => null)) as { result?: { items?: Array<Record<string, unknown>> } } | null;\n const items = Array.isArray(body?.result?.items) ? body.result.items : [];\n const exactMatch = items.find((item) => {\n const displayName = typeof item.displayName === 'string'\n ? item.displayName\n : typeof item.display_name === 'string'\n ? item.display_name\n : '';\n return displayName.trim().toLowerCase() === customerQuery.trim().toLowerCase();\n }) ?? items[0];\n return exactMatch ? readId(exactMatch, ['id', 'entityId', 'companyId']) : null;\n}\n\nasync function resolveSalesChannelId(page: Page, token: string, channelQuery: string): Promise<string | null> {\n const resolveItems = async (search?: string): Promise<ChannelListItem[]> => {\n const params = new URLSearchParams({ page: '1', pageSize: '5', isActive: 'true' });\n if (search && search.trim().length > 0) params.set('search', search.trim());\n const response = await apiRequest(page.request, 'GET', `/api/sales/channels?${params.toString()}`, {\n token,\n }).catch(() => null);\n const body = (await response?.json().catch(() => null)) as { result?: { items?: ChannelListItem[] }; items?: ChannelListItem[] } | null;\n return Array.isArray(body?.result?.items)\n ? body.result.items\n : Array.isArray(body?.items)\n ? body.items\n : [];\n };\n const initialItems = await resolveItems(channelQuery);\n const items = initialItems.length > 0 ? initialItems : await resolveItems();\n const normalizedQuery = channelQuery.trim().toLowerCase();\n const exactMatch = items.find((item) => item.name?.trim().toLowerCase() === normalizedQuery)\n ?? items.find((item) => item.code?.trim().toLowerCase() === normalizedQuery)\n ?? items.find((item) => item.code === 'online')\n ?? items[0];\n return exactMatch?.id ?? null;\n}\n\nasync function createSalesDocumentFixture(\n page: Page,\n token: string,\n kind: DocumentKind,\n customerQuery: string,\n channelQuery: string,\n): Promise<string> {\n const customerEntityId = await resolveCustomerEntityId(page, token, customerQuery);\n const channelId = await resolveSalesChannelId(page, token, channelQuery);\n const payload: Record<string, unknown> = {\n currencyCode: 'USD',\n };\n if (customerEntityId) payload.customerEntityId = customerEntityId;\n if (channelId) payload.channelId = channelId;\n\n const response = await apiRequest(page.request, 'POST', kind === 'quote' ? '/api/sales/quotes' : '/api/sales/orders', {\n token,\n data: payload,\n });\n const body = (await response.json().catch(() => null)) as unknown;\n if (!response.ok()) {\n throw new Error(`Failed to create sales ${kind} fixture via API.`);\n }\n const id = readId(body, ['id', kind === 'quote' ? 'quoteId' : 'orderId']);\n if (!id) {\n throw new Error(`Missing sales ${kind} id in API fallback response.`);\n }\n return id;\n}\n\nasync function waitForDocumentLoaded(page: Page, timeout = TEST_WAIT_TIMEOUT_MS): Promise<boolean> {\n const itemsButton = page.getByRole('button', { name: /^Items$/i }).first();\n if (await itemsButton.isVisible().catch(() => false)) return true;\n const loadingIndicator = page.getByText(/Loading document\u2026|Loading document\\.\\.\\./i).first();\n const isLoading = await loadingIndicator.isVisible().catch(() => false);\n if (isLoading) {\n await loadingIndicator.waitFor({ state: 'hidden', timeout }).catch(() => {});\n }\n return await itemsButton.waitFor({ state: 'visible', timeout: Math.min(timeout, 5_000) }).then(() => true).catch(() => false);\n}\n\nasync function openSalesDocumentPage(page: Page, id: string, kind: DocumentKind): Promise<void> {\n const documentUrl = `/backend/sales/documents/${id}?kind=${kind}`;\n await page.goto(documentUrl, { waitUntil: 'domcontentloaded' });\n\n if (await waitForDocumentLoaded(page, TEST_WAIT_TIMEOUT_MS)) return;\n\n for (let attempt = 0; attempt < 3; attempt += 1) {\n const recovered = await recoverGenericErrorPageIfPresent(page);\n if (recovered) {\n if (await waitForDocumentLoaded(page, TEST_WAIT_TIMEOUT_MS)) return;\n continue;\n }\n await page.goto(documentUrl, { waitUntil: 'domcontentloaded' });\n if (await waitForDocumentLoaded(page, TEST_WAIT_TIMEOUT_MS)) return;\n }\n await expect(page.getByRole('button', { name: /^Items$/i }).first()).toBeVisible({\n timeout: TEST_WAIT_TIMEOUT_MS,\n });\n}\n\nasync function ensureSalesDocumentReady(page: Page): Promise<void> {\n if (await waitForDocumentLoaded(page, TEST_WAIT_TIMEOUT_MS)) return;\n\n for (let attempt = 0; attempt < 3; attempt += 1) {\n const recovered = await recoverGenericErrorPageIfPresent(page);\n if (recovered) {\n if (await waitForDocumentLoaded(page, TEST_WAIT_TIMEOUT_MS)) return;\n continue;\n }\n await page.reload({ waitUntil: 'domcontentloaded' }).catch(() => {});\n if (await waitForDocumentLoaded(page, TEST_WAIT_TIMEOUT_MS)) return;\n }\n await expect(page.getByRole('button', { name: /^Items$/i }).first()).toBeVisible({\n timeout: TEST_WAIT_TIMEOUT_MS,\n });\n}\n\nasync function selectAnyLookupOption(root: Locator): Promise<boolean> {\n const selectButton = root.getByRole('button', { name: /^Select$/i }).first();\n if (await selectButton.isVisible().catch(() => false)) {\n await selectButton.click().catch(() => {});\n return true;\n }\n\n const row = root.locator('[role=\"button\"]').first();\n if (await row.isVisible().catch(() => false)) {\n await row.click().catch(() => {});\n return true;\n }\n\n return false;\n}\n\nasync function selectLookupValue(\n input: Locator,\n query: string,\n preferredRowPattern?: RegExp,\n): Promise<boolean> {\n if (!(await input.isVisible().catch(() => false)) && (await input.count().catch(() => 0)) === 0) return false;\n await waitForStableVisibility(input, 4_000).catch(() => {});\n await input.click().catch(() => {});\n await input.press('ControlOrMeta+a').catch(() => {});\n await input.fill(query).catch(() => {});\n\n const root = lookupRootFromInput(input);\n await waitForLookupIdle(root);\n\n const selectByPreferredRow = async (): Promise<boolean> => {\n if (!preferredRowPattern) return false;\n const row = root.locator('[role=\"button\"]').filter({ hasText: preferredRowPattern }).first();\n const action = row.getByRole('button', { name: /^Select$/i }).first();\n if (await action.isVisible().catch(() => false)) {\n await action.click();\n return true;\n }\n if ((await row.isVisible().catch(() => false))) {\n await row.click().catch(() => {});\n return true;\n }\n return false;\n };\n\n if (await selectByPreferredRow()) return true;\n\n const deadline = Date.now() + 4_000;\n while (Date.now() < deadline) {\n await waitForLookupIdle(root);\n if (await selectAnyLookupOption(root)) return true;\n if (await selectByPreferredRow()) return true;\n const selectedButton = root.getByRole('button', { name: /^Selected$/i }).first();\n if (await selectedButton.isVisible().catch(() => false)) {\n return true;\n }\n await input.page().waitForTimeout(250);\n }\n\n await input.press('ArrowDown').catch(() => {});\n await input.press('Enter').catch(() => {});\n const selectedButton = root.getByRole('button', { name: /^Selected$/i }).first();\n if (await selectedButton.isVisible().catch(() => false)) {\n return true;\n }\n return await selectAnyLookupOption(root);\n}\n\nexport async function createSalesDocument(page: Page, options: CreateDocumentOptions): Promise<string> {\n const fixtureContext = await ensureSalesDocumentFixtures(page, options);\n const customerQuery = fixtureContext.customerQuery;\n const channelQuery = fixtureContext.channelQuery;\n\n let createPageReady = false;\n for (let attempt = 0; attempt < 3; attempt += 1) {\n await page.goto(`/backend/sales/documents/create?kind=${options.kind}`, {\n waitUntil: 'domcontentloaded',\n });\n await page.getByText(/Loading\u2026|Loading\\.\\.\\./i).first().waitFor({ state: 'hidden', timeout: TEST_WAIT_TIMEOUT_MS }).catch(() => {});\n const createButton = page.getByRole('button', { name: /^Create$/i }).first();\n if (await createButton.isVisible().catch(() => false)) {\n createPageReady = true;\n break;\n }\n const recovered = await recoverGenericErrorPageIfPresent(page);\n if (!recovered && attempt === 2) {\n await expect(createButton).toBeVisible({ timeout: TEST_WAIT_TIMEOUT_MS });\n }\n }\n if (!createPageReady) {\n const token = await getAuthToken(page.request, 'admin');\n const id = await createSalesDocumentFixture(page, token, options.kind, customerQuery, channelQuery);\n await openSalesDocumentPage(page, id, options.kind);\n return id;\n }\n await expect(page.getByRole('button', { name: /^Create$/i }).first()).toBeVisible({\n timeout: TEST_WAIT_TIMEOUT_MS,\n });\n\n const generateButton = page.getByRole('button', { name: /Generate/i }).first();\n const createButton = page.getByRole('button', { name: /^Create$/i }).first();\n const hasGenerateButton = (await generateButton.count()) > 0;\n if (hasGenerateButton) {\n await expect(generateButton).toBeVisible({ timeout: 10_000 });\n await expect(generateButton).toBeEnabled({ timeout: 30_000 });\n }\n\n await page.getByText('Document type').click();\n const customerSelected = await selectLookupValue(\n page.getByRole('textbox', { name: /Search customers/i }).first(),\n customerQuery,\n new RegExp(escapeRegExp(customerQuery), 'i'),\n );\n if (!customerSelected) throw new Error(`Could not select customer \"${customerQuery}\" while creating sales ${options.kind}.`);\n\n await selectLookupValue(\n page.getByRole('textbox', { name: /Select a channel/i }).first(),\n channelQuery,\n new RegExp(escapeRegExp(channelQuery), 'i'),\n );\n\n await selectFirstAddressIfAvailable(page);\n\n const createEnabled = await createButton.isEnabled().catch(() => false);\n if (!createEnabled) {\n const token = await getAuthToken(page.request, 'admin');\n const id = await createSalesDocumentFixture(page, token, options.kind, customerQuery, channelQuery);\n await openSalesDocumentPage(page, id, options.kind);\n return id;\n }\n\n await createButton.click();\n const navigated = await page.waitForURL(\n new RegExp(\n `/backend/sales/(?:documents/[0-9a-f-]{36}\\\\?kind=${options.kind}|${options.kind === 'order' ? 'orders' : 'quotes'}/[0-9a-f-]{36})$`,\n 'i',\n ),\n { timeout: TEST_WAIT_TIMEOUT_MS },\n ).then(() => true).catch(() => false);\n if (!navigated) {\n const token = await getAuthToken(page.request, 'admin');\n const id = await createSalesDocumentFixture(page, token, options.kind, customerQuery, channelQuery);\n await openSalesDocumentPage(page, id, options.kind);\n return id;\n }\n\n const match = page.url().match(/\\/backend\\/sales\\/(?:documents|orders|quotes)\\/([0-9a-f-]{36})/i);\n if (!match) {\n throw new Error(`Could not resolve document id from URL: ${page.url()}`);\n }\n const loaded = await waitForDocumentLoaded(page, TEST_WAIT_TIMEOUT_MS);\n if (!loaded) {\n await openSalesDocumentPage(page, match[1], options.kind);\n }\n return match[1];\n}\n\nfunction lineDialog(page: Page): Locator {\n return page.getByRole('dialog', { name: /Add line|Edit line/i });\n}\n\nasync function selectFirstOption(container: Locator, rowNamePattern: RegExp): Promise<void> {\n const optionRow = container.getByRole('button', { name: rowNamePattern }).first();\n await optionRow.waitFor({ state: 'visible', timeout: 4_000 }).catch(() => {});\n if ((await optionRow.count()) === 0) return;\n\n const selectButton = optionRow.getByRole('button', { name: /^Select$/i }).first();\n if ((await selectButton.count()) > 0) {\n await selectButton.click();\n return;\n }\n await optionRow.click();\n}\n\nasync function selectFirstLookupOption(input: Locator, rowNamePattern: RegExp): Promise<void> {\n const root = lookupRootFromInput(input);\n await waitForLookupIdle(root);\n await selectFirstOption(root, rowNamePattern);\n}\n\nasync function selectShipmentMethod(dialog: Locator): Promise<void> {\n const shippingMethodInput = dialog.getByPlaceholder(/Select method/i).first();\n if ((await shippingMethodInput.count()) === 0) return;\n const selected = await selectLookupValue(shippingMethodInput, 'Standard', /standard ground|express air|standard/i);\n if (!selected) {\n await selectFirstLookupOption(shippingMethodInput, /standard ground|express air|standard/i);\n }\n}\n\nasync function selectShipmentStatus(dialog: Locator): Promise<void> {\n const statusInput = dialog.getByPlaceholder(/Select shipment status/i).first();\n if ((await statusInput.count()) > 0) {\n const selected = await selectLookupValue(statusInput, 'Shipped', /shipped|in transit|packed/i);\n if (selected) return;\n await selectFirstLookupOption(statusInput, /shipped|in transit|packed/i);\n return;\n }\n}\n\nasync function selectShipmentAddress(dialog: Locator): Promise<void> {\n const addressInput = dialog.getByPlaceholder(/Select address/i).first();\n if ((await addressInput.count()) === 0) return;\n const currentValue = await addressInput.inputValue().catch(() => '');\n if (currentValue.trim().length > 0) return;\n const selected = await selectLookupValue(addressInput, 'Address', /shipping address|document address|address/i);\n if (!selected) {\n await selectFirstLookupOption(addressInput, /shipping address|document address|address/i);\n }\n}\n\nasync function fillShipmentQuantity(dialog: Locator): Promise<void> {\n const quantityInputs = dialog.getByRole('spinbutton');\n const count = await quantityInputs.count();\n for (let index = 0; index < count; index += 1) {\n const input = quantityInputs.nth(index);\n const isVisible = await input.isVisible().catch(() => false);\n const isEnabled = await input.isEnabled().catch(() => false);\n if (!isVisible || !isEnabled) continue;\n await input.fill('1').catch(() => {});\n }\n}\n\nasync function fillShipmentDates(dialog: Locator): Promise<void> {\n const now = new Date();\n const day = String(now.getDate()).padStart(2, '0');\n const month = String(now.getMonth() + 1).padStart(2, '0');\n const year = String(now.getFullYear());\n const shippedDateValue = `${day}/${month}/${year}`;\n\n const shippedDateInput = dialog.getByLabel(/Shipped date/i).first();\n if ((await shippedDateInput.count()) > 0) {\n const currentValue = await shippedDateInput.inputValue().catch(() => '');\n if (currentValue.trim().length === 0) {\n await shippedDateInput.fill(shippedDateValue).catch(() => {});\n }\n }\n}\n\nasync function fillShipmentNumber(dialog: Locator, shipmentNumber: string): Promise<void> {\n const shipmentNumberInput = dialog.getByRole('textbox').first();\n if (!(await shipmentNumberInput.isVisible().catch(() => false)) && (await shipmentNumberInput.count().catch(() => 0)) === 0) {\n return;\n }\n await waitForStableVisibility(shipmentNumberInput, 4_000).catch(() => {});\n await shipmentNumberInput.fill(shipmentNumber).catch(() => {});\n await shipmentNumberInput.press('Tab').catch(() => {});\n}\n\nexport async function addCustomLine(page: Page, options: AddLineOptions): Promise<void> {\n await ensureSalesDocumentReady(page);\n await page.getByRole('button', { name: /^Items$/i }).click();\n const addItemButton = page.getByRole('button', { name: /Add item/i }).first();\n await expect(addItemButton).toBeVisible({ timeout: TEST_WAIT_TIMEOUT_MS });\n await expect(addItemButton).toBeEnabled({ timeout: TEST_WAIT_TIMEOUT_MS });\n await addItemButton.click();\n\n const dialog = lineDialog(page);\n await expect(dialog).toBeVisible();\n\n const customLineButton = dialog.getByRole('button', { name: /Custom line/i });\n await expect(customLineButton).toBeVisible({ timeout: TEST_WAIT_TIMEOUT_MS });\n await customLineButton.click();\n\n const nameInput = dialog.getByRole('textbox', { name: /Optional line name/i });\n await expect(nameInput).toBeVisible({ timeout: TEST_WAIT_TIMEOUT_MS });\n await nameInput.fill(options.name);\n await dialog.getByRole('textbox', { name: '0.00' }).fill(String(options.unitPriceGross));\n await dialog.getByRole('textbox', { name: '1' }).fill(String(options.quantity));\n\n if (options.taxClassName) {\n const taxClassSelect = dialog\n .locator('select')\n .filter({ has: dialog.locator('option', { hasText: /No tax class selected/i }) })\n .first();\n if ((await taxClassSelect.count()) > 0) {\n await taxClassSelect.selectOption({ label: options.taxClassName });\n }\n }\n\n const submitButton = dialog.getByRole('button', { name: /Add item/i });\n await expect(submitButton).toBeVisible({ timeout: TEST_WAIT_TIMEOUT_MS });\n await expect(submitButton).toBeEnabled({ timeout: TEST_WAIT_TIMEOUT_MS });\n const lineRow = page.getByRole('row', { name: new RegExp(escapeRegExp(options.name), 'i') });\n for (let attempt = 0; attempt < 2; attempt += 1) {\n await submitButton.click();\n await Promise.race([\n dialog.waitFor({ state: 'hidden', timeout: 3_000 }).catch(() => {}),\n lineRow.waitFor({ state: 'visible', timeout: 3_000 }).catch(() => {}),\n ]);\n if (await lineRow.isVisible().catch(() => false)) break;\n if (!(await dialog.isVisible().catch(() => false))) break;\n }\n\n if (await dialog.isVisible().catch(() => false)) {\n await expect(dialog).toBeHidden({ timeout: TEST_WAIT_TIMEOUT_MS });\n }\n await page.getByRole('button', { name: /^Items$/i }).click().catch(() => {});\n await expect(lineRow).toBeVisible({ timeout: TEST_WAIT_TIMEOUT_MS });\n}\n\nexport async function updateLineQuantity(page: Page, lineName: string, quantity: number): Promise<void> {\n await page.getByRole('button', { name: /^Items$/i }).click();\n const row = page.getByRole('row', { name: new RegExp(escapeRegExp(lineName), 'i') });\n await row.click();\n\n const dialog = page.getByRole('dialog', { name: /Edit line/i });\n await expect(dialog).toBeVisible();\n await dialog.getByRole('textbox', { name: '1' }).fill(String(quantity));\n await dialog.getByRole('button', { name: /Save changes/i }).click();\n\n await expect(page.getByRole('row', { name: new RegExp(`${escapeRegExp(lineName)}.*\\\\b${quantity}\\\\b`, 'i') })).toBeVisible();\n}\n\nexport async function deleteLine(page: Page, lineName: string): Promise<void> {\n await page.getByRole('button', { name: /^Items$/i }).click();\n const row = page.getByRole('row', { name: new RegExp(escapeRegExp(lineName), 'i') });\n await expect(row).toBeVisible();\n await row.locator('button').last().click();\n\n const confirmDialog = page.getByRole('alertdialog');\n if (await confirmDialog.isVisible().catch(() => false)) {\n await confirmDialog.getByRole('button', { name: /^Delete$/i }).first().click();\n await expect(confirmDialog).toBeHidden();\n }\n\n await expect(page.getByRole('row', { name: new RegExp(escapeRegExp(lineName), 'i') })).toHaveCount(0);\n}\n\nexport async function addAdjustment(page: Page, options: AddAdjustmentOptions): Promise<void> {\n const adjustmentsTab = page.getByRole('button', { name: /^Adjustments$/i }).first();\n await waitForStableVisibility(adjustmentsTab, TEST_WAIT_TIMEOUT_MS);\n await adjustmentsTab.click();\n const addAdjustmentButton = page.getByRole('button', { name: /Add adjustment/i }).first();\n await waitForStableVisibility(addAdjustmentButton, TEST_WAIT_TIMEOUT_MS);\n await addAdjustmentButton.click();\n\n const dialog = page.getByRole('dialog', { name: /Add adjustment/i });\n await expect(dialog).toBeVisible();\n const adjustmentRow = page.getByRole('row', { name: new RegExp(escapeRegExp(options.label), 'i') });\n const fillAdjustmentForm = async (): Promise<void> => {\n await dialog.getByText(/Loading adjustments/i).waitFor({ state: 'hidden', timeout: 3_000 }).catch(() => {});\n const kindSelect = dialog.locator('select').first();\n await expect(kindSelect).toHaveValue(/^custom$/i, { timeout: 3_000 });\n\n const labelInput = dialog.getByPlaceholder(/e\\.g\\. Shipping fee/i).first();\n await expect(labelInput).toBeVisible({ timeout: TEST_WAIT_TIMEOUT_MS });\n await labelInput.fill(options.label);\n await expect(labelInput).toHaveValue(options.label, { timeout: 2_000 });\n\n if ((await kindSelect.count()) > 0) {\n const expectedKindValue = normalizeAdjustmentKindValue(options.kindLabel ?? 'Surcharge');\n await kindSelect.locator('option', { hasText: new RegExp(`^${escapeRegExp(options.kindLabel ?? 'Surcharge')}$`, 'i') })\n .first()\n .waitFor({ state: 'attached', timeout: 2_000 })\n .catch(() => {});\n await kindSelect.selectOption({ label: options.kindLabel ?? 'Surcharge' }).catch(async () => {\n await kindSelect.selectOption({ label: 'Custom' });\n });\n await expect(kindSelect).toHaveValue(new RegExp(`^${escapeRegExp(expectedKindValue)}$`, 'i'), {\n timeout: 2_000,\n });\n }\n\n const fixedAmountButton = dialog.getByRole('button', { name: /^Fixed amount$/i }).first();\n if ((await fixedAmountButton.count()) > 0) {\n await fixedAmountButton.click().catch(() => {});\n }\n\n const enabledAmountInputs = dialog.locator('input[placeholder=\"0.00\"]:not([disabled])');\n await expect(enabledAmountInputs.first()).toBeVisible({ timeout: TEST_WAIT_TIMEOUT_MS });\n if ((await enabledAmountInputs.count()) > 0) {\n await enabledAmountInputs.first().fill(String(options.netAmount));\n await expect(enabledAmountInputs.first()).toHaveValue(String(options.netAmount), { timeout: 2_000 }).catch(() => {});\n }\n };\n\n let saved = false;\n for (let attempt = 0; attempt < 3; attempt += 1) {\n await fillAdjustmentForm();\n const submitButton = dialog.getByRole('button', { name: /Add adjustment/i }).first();\n await waitForStableVisibility(submitButton, 4_000).catch(() => {});\n await submitButton.click();\n await Promise.race([\n dialog.waitFor({ state: 'hidden', timeout: 3_000 }).catch(() => {}),\n adjustmentRow.waitFor({ state: 'visible', timeout: 3_000 }).catch(() => {}),\n ]);\n saved =\n !(await dialog.isVisible().catch(() => false)) ||\n (await adjustmentRow.isVisible().catch(() => false));\n if (saved) break;\n }\n\n if (await dialog.isVisible().catch(() => false)) {\n await expect(dialog).toBeHidden({ timeout: 5_000 });\n }\n if (!(await adjustmentRow.isVisible().catch(() => false))) {\n await adjustmentsTab.click().catch(() => {});\n await adjustmentRow.waitFor({ state: 'visible', timeout: 2_000 }).catch(() => {});\n }\n}\n\nexport async function addPayment(page: Page, amount: number): Promise<{ amountLabel: string; added: boolean }> {\n await ensureSalesDocumentReady(page);\n const paymentsTab = page.getByRole('button', { name: /^Payments$/i }).first();\n await waitForStableVisibility(paymentsTab, TEST_WAIT_TIMEOUT_MS);\n await paymentsTab.click();\n const amountLabel = amount.toFixed(2);\n const amountInputValue = String(Math.max(1, Math.round(amount)));\n const addPaymentButton = page.getByRole('button', { name: /Add payment/i }).first();\n await waitForStableVisibility(addPaymentButton, TEST_WAIT_TIMEOUT_MS);\n await expect(addPaymentButton).toBeEnabled({ timeout: TEST_WAIT_TIMEOUT_MS });\n await addPaymentButton.click();\n\n const dialog = page.getByRole('dialog', { name: /Add payment/i });\n const amountInput = dialog.locator('input[placeholder=\"0.00\"]').first();\n await waitForDialogFieldReady(dialog, amountInput, /Loading payment methods\u2026|Loading payment methods\\.\\.\\./i);\n const setAmount = async (): Promise<void> => {\n const refreshedAmountInput = dialog.locator('input[placeholder=\"0.00\"]').first();\n await waitForStableVisibility(refreshedAmountInput, 4_000).catch(() => {});\n await refreshedAmountInput.fill(amountInputValue).catch(() => {});\n await refreshedAmountInput.press('Tab').catch(() => {});\n };\n const selectMethodInput = dialog.getByPlaceholder(/Search payment method/i).first();\n const statusInput = dialog.getByPlaceholder(/Select status/i).first();\n await setAmount();\n await waitForStableVisibility(selectMethodInput, 4_000).catch(() => {});\n await selectLookupValue(selectMethodInput, 'Bank', /bank transfer|credit card|cash on delivery/i).catch(() => false);\n await waitForStableVisibility(statusInput, 4_000).catch(() => {});\n await selectLookupValue(statusInput, 'Pending', /pending|captured/i).catch(() => false);\n const saveButton = dialog.getByRole('button', { name: /Save/i }).first();\n const operationMessage = page.getByText(/Last operation:\\s*Create payment/i).first();\n for (let attempt = 0; attempt < 2; attempt += 1) {\n await setAmount();\n await selectLookupValue(selectMethodInput, 'Bank', /bank transfer|credit card|cash on delivery/i).catch(() => false);\n await selectLookupValue(statusInput, 'Pending', /pending|captured/i).catch(() => false);\n await waitForStableVisibility(saveButton, 4_000).catch(() => {});\n await saveButton.click();\n await Promise.race([\n dialog.waitFor({ state: 'hidden', timeout: 3_500 }).catch(() => {}),\n operationMessage.waitFor({ state: 'visible', timeout: 3_500 }).catch(() => {}),\n dialog.getByText(/This field is required/i).first().waitFor({ state: 'visible', timeout: 3_500 }).catch(() => {}),\n ]);\n if (!(await dialog.isVisible().catch(() => false))) break;\n if (await operationMessage.isVisible().catch(() => false)) break;\n await waitForOptionalTextToDisappear(dialog, /Loading payment methods\u2026|Loading payment methods\\.\\.\\./i, 3_000);\n }\n if (await dialog.isVisible().catch(() => false)) {\n await dialog.press('Escape').catch(() => {});\n await dialog.waitFor({ state: 'hidden', timeout: 1_500 }).catch(() => {});\n }\n await operationMessage.waitFor({ state: 'visible', timeout: 2_500 }).catch(() => {});\n const added = await operationMessage.isVisible().catch(() => false);\n return { amountLabel, added };\n}\n\nexport async function addShipment(page: Page): Promise<{ trackingNumber: string; shipmentNumber: string; added: boolean }> {\n await ensureSalesDocumentReady(page);\n await ensureShippingMethodFixture(page);\n const shipmentsTab = page.getByRole('button', { name: /^Shipments$/i }).first();\n await waitForStableVisibility(shipmentsTab, TEST_WAIT_TIMEOUT_MS);\n await shipmentsTab.click();\n const trackingNumber = `SHIP-${Date.now()}`;\n const shipmentNumber = String(Date.now());\n const addShipmentButton = page.getByRole('button', { name: /Add shipment/i }).first();\n await waitForStableVisibility(addShipmentButton, TEST_WAIT_TIMEOUT_MS);\n await expect(addShipmentButton).toBeEnabled({ timeout: TEST_WAIT_TIMEOUT_MS });\n await addShipmentButton.click();\n\n const dialog = page.getByRole('dialog', { name: /Add shipment/i });\n const shipmentNumberInput = dialog.getByRole('textbox').first();\n await waitForDialogFieldReady(dialog, shipmentNumberInput, /Loading shipments\u2026|Loading shipments\\.\\.\\./i);\n await fillShipmentNumber(dialog, shipmentNumber);\n const trackingInput = dialog.getByPlaceholder(/One per line or comma separated/i).first();\n await waitForStableVisibility(trackingInput, 4_000).catch(() => {});\n await trackingInput.fill(trackingNumber).catch(() => {});\n await selectShipmentMethod(dialog);\n await selectShipmentStatus(dialog);\n await selectShipmentAddress(dialog);\n await fillShipmentQuantity(dialog);\n await fillShipmentDates(dialog);\n await fillShipmentNumber(dialog, shipmentNumber);\n\n await dialog.getByText(/Searching\u2026|Searching\\.\\.\\./i).first().waitFor({ state: 'hidden', timeout: TEST_WAIT_TIMEOUT_MS }).catch(() => {});\n const saveButton = dialog.getByRole('button', { name: /^Save\\b/i }).first();\n const canClickSave = (await saveButton.count()) > 0 && (await saveButton.isVisible().catch(() => false));\n if (canClickSave) {\n await saveButton.click({ timeout: TEST_WAIT_TIMEOUT_MS }).catch(() => {});\n } else {\n await dialog.press('ControlOrMeta+Enter').catch(() => {});\n }\n\n let closed = await dialog\n .waitFor({ state: 'hidden', timeout: TEST_WAIT_TIMEOUT_MS })\n .then(() => true)\n .catch(() => false);\n\n if (!closed) {\n for (let attempt = 0; attempt < 2; attempt += 1) {\n if (!(await dialog.isVisible().catch(() => false))) break;\n await selectShipmentMethod(dialog);\n await selectShipmentAddress(dialog);\n await fillShipmentQuantity(dialog);\n await fillShipmentDates(dialog);\n await fillShipmentNumber(dialog, shipmentNumber);\n if (canClickSave) {\n await saveButton.click({ timeout: 2_000 }).catch(() => {});\n } else {\n await dialog.press('ControlOrMeta+Enter').catch(() => {});\n }\n closed = await dialog\n .waitFor({ state: 'hidden', timeout: 2_000 })\n .then(() => true)\n .catch(() => false);\n if (closed) break;\n }\n }\n\n if (!closed) {\n return { trackingNumber, shipmentNumber, added: false };\n }\n\n await page.getByRole('button', { name: /^Shipments$/i }).click();\n const shipmentLabel = page.getByText(new RegExp(`Shipment\\\\s+${escapeRegExp(shipmentNumber)}`, 'i')).first();\n const added = await shipmentLabel\n .waitFor({ state: 'visible', timeout: TEST_WAIT_TIMEOUT_MS })\n .then(() => true)\n .catch(() => false);\n return { trackingNumber, shipmentNumber, added };\n}\n\nexport async function readGrandTotalGross(page: Page): Promise<number> {\n const row = page.getByRole('row', { name: /Grand total \\(gross\\)/i }).first();\n await expect(row).toBeVisible();\n const text = (await row.innerText()).trim();\n return parseCurrencyAmount(text);\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["selectedButton", "createButton"]
7
+ }
@@ -0,0 +1,27 @@
1
+ const OM_EVENT_NAME = "om:event";
2
+ const CAPTURED_EVENTS_KEY = "__capturedOmEvents";
3
+ async function installOmEventCollector(page) {
4
+ await page.evaluate(({ eventName, storageKey }) => {
5
+ ;
6
+ window[storageKey] = [];
7
+ window.addEventListener(eventName, (event) => {
8
+ const detail = event.detail;
9
+ if (!detail || typeof detail !== "object") return;
10
+ const store = window[storageKey];
11
+ if (!Array.isArray(store)) return;
12
+ store.push(detail);
13
+ });
14
+ }, { eventName: OM_EVENT_NAME, storageKey: CAPTURED_EVENTS_KEY });
15
+ }
16
+ async function getCapturedOmEvents(page) {
17
+ return page.evaluate((storageKey) => {
18
+ const store = window[storageKey];
19
+ if (!Array.isArray(store)) return [];
20
+ return store;
21
+ }, CAPTURED_EVENTS_KEY);
22
+ }
23
+ export {
24
+ getCapturedOmEvents,
25
+ installOmEventCollector
26
+ };
27
+ //# sourceMappingURL=sseEventCollector.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/helpers/integration/sseEventCollector.ts"],
4
+ "sourcesContent": ["import type { Page } from '@playwright/test'\n\nconst OM_EVENT_NAME = 'om:event'\nconst CAPTURED_EVENTS_KEY = '__capturedOmEvents'\n\nexport type CapturedEvent = {\n id: string\n payload?: Record<string, unknown>\n}\n\nexport async function installOmEventCollector(page: Page): Promise<void> {\n await page.evaluate(({ eventName, storageKey }) => {\n ;(window as unknown as Record<string, unknown>)[storageKey] = []\n window.addEventListener(eventName, (event: Event) => {\n const detail = (event as CustomEvent<CapturedEvent>).detail\n if (!detail || typeof detail !== 'object') return\n const store = (window as unknown as Record<string, unknown>)[storageKey]\n if (!Array.isArray(store)) return\n store.push(detail)\n })\n }, { eventName: OM_EVENT_NAME, storageKey: CAPTURED_EVENTS_KEY })\n}\n\nexport async function getCapturedOmEvents(page: Page): Promise<CapturedEvent[]> {\n return page.evaluate((storageKey) => {\n const store = (window as unknown as Record<string, unknown>)[storageKey]\n if (!Array.isArray(store)) return []\n return store as CapturedEvent[]\n }, CAPTURED_EVENTS_KEY)\n}\n"],
5
+ "mappings": "AAEA,MAAM,gBAAgB;AACtB,MAAM,sBAAsB;AAO5B,eAAsB,wBAAwB,MAA2B;AACvE,QAAM,KAAK,SAAS,CAAC,EAAE,WAAW,WAAW,MAAM;AACjD;AAAC,IAAC,OAA8C,UAAU,IAAI,CAAC;AAC/D,WAAO,iBAAiB,WAAW,CAAC,UAAiB;AACnD,YAAM,SAAU,MAAqC;AACrD,UAAI,CAAC,UAAU,OAAO,WAAW,SAAU;AAC3C,YAAM,QAAS,OAA8C,UAAU;AACvE,UAAI,CAAC,MAAM,QAAQ,KAAK,EAAG;AAC3B,YAAM,KAAK,MAAM;AAAA,IACnB,CAAC;AAAA,EACH,GAAG,EAAE,WAAW,eAAe,YAAY,oBAAoB,CAAC;AAClE;AAEA,eAAsB,oBAAoB,MAAsC;AAC9E,SAAO,KAAK,SAAS,CAAC,eAAe;AACnC,UAAM,QAAS,OAA8C,UAAU;AACvE,QAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,WAAO;AAAA,EACT,GAAG,mBAAmB;AACxB;",
6
+ "names": []
7
+ }
@@ -0,0 +1,47 @@
1
+ import { expect } from "@playwright/test";
2
+ import { apiRequest } from "./api.js";
3
+ async function createStaffTeamFixture(request, token, name) {
4
+ const response = await apiRequest(request, "POST", "/api/staff/teams", {
5
+ token,
6
+ data: { name: name ?? `QA Team ${Date.now()}` }
7
+ });
8
+ expect(response.ok(), `Failed to create staff team fixture: ${response.status()}`).toBeTruthy();
9
+ const body = await response.json();
10
+ expect(typeof body.id === "string" && body.id.length > 0).toBeTruthy();
11
+ return body.id;
12
+ }
13
+ async function createStaffTeamMemberFixture(request, token, input) {
14
+ const response = await apiRequest(request, "POST", "/api/staff/team-members", {
15
+ token,
16
+ data: { displayName: input?.displayName ?? `QA Member ${Date.now()}` }
17
+ });
18
+ expect(response.ok(), `Failed to create staff team member fixture: ${response.status()}`).toBeTruthy();
19
+ const body = await response.json();
20
+ expect(typeof body.id === "string" && body.id.length > 0).toBeTruthy();
21
+ return body.id;
22
+ }
23
+ async function createStaffTeamRoleFixture(request, token, input) {
24
+ const response = await apiRequest(request, "POST", "/api/staff/team-roles", {
25
+ token,
26
+ data: { name: input?.name ?? `QA Role ${Date.now()}` }
27
+ });
28
+ expect(response.ok(), `Failed to create staff team role fixture: ${response.status()}`).toBeTruthy();
29
+ const body = await response.json();
30
+ expect(typeof body.id === "string" && body.id.length > 0).toBeTruthy();
31
+ return body.id;
32
+ }
33
+ async function deleteStaffEntityIfExists(request, token, path, id) {
34
+ if (!token || !id) return;
35
+ try {
36
+ await apiRequest(request, "DELETE", `${path}?id=${encodeURIComponent(id)}`, { token });
37
+ } catch {
38
+ return;
39
+ }
40
+ }
41
+ export {
42
+ createStaffTeamFixture,
43
+ createStaffTeamMemberFixture,
44
+ createStaffTeamRoleFixture,
45
+ deleteStaffEntityIfExists
46
+ };
47
+ //# sourceMappingURL=staffFixtures.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/helpers/integration/staffFixtures.ts"],
4
+ "sourcesContent": ["import { expect, type APIRequestContext } from '@playwright/test';\nimport { apiRequest } from './api';\n\nexport async function createStaffTeamFixture(\n request: APIRequestContext,\n token: string,\n name?: string,\n): Promise<string> {\n const response = await apiRequest(request, 'POST', '/api/staff/teams', {\n token,\n data: { name: name ?? `QA Team ${Date.now()}` },\n });\n expect(response.ok(), `Failed to create staff team fixture: ${response.status()}`).toBeTruthy();\n const body = (await response.json()) as { id?: string };\n expect(typeof body.id === 'string' && body.id.length > 0).toBeTruthy();\n return body.id as string;\n}\n\nexport async function createStaffTeamMemberFixture(\n request: APIRequestContext,\n token: string,\n input?: { displayName?: string },\n): Promise<string> {\n const response = await apiRequest(request, 'POST', '/api/staff/team-members', {\n token,\n data: { displayName: input?.displayName ?? `QA Member ${Date.now()}` },\n });\n expect(response.ok(), `Failed to create staff team member fixture: ${response.status()}`).toBeTruthy();\n const body = (await response.json()) as { id?: string };\n expect(typeof body.id === 'string' && body.id.length > 0).toBeTruthy();\n return body.id as string;\n}\n\nexport async function createStaffTeamRoleFixture(\n request: APIRequestContext,\n token: string,\n input?: { name?: string },\n): Promise<string> {\n const response = await apiRequest(request, 'POST', '/api/staff/team-roles', {\n token,\n data: { name: input?.name ?? `QA Role ${Date.now()}` },\n });\n expect(response.ok(), `Failed to create staff team role fixture: ${response.status()}`).toBeTruthy();\n const body = (await response.json()) as { id?: string };\n expect(typeof body.id === 'string' && body.id.length > 0).toBeTruthy();\n return body.id as string;\n}\n\nexport async function deleteStaffEntityIfExists(\n request: APIRequestContext,\n token: string | null,\n path: string,\n id: string | null,\n): Promise<void> {\n if (!token || !id) return;\n try {\n await apiRequest(request, 'DELETE', `${path}?id=${encodeURIComponent(id)}`, { token });\n } catch {\n return;\n }\n}\n"],
5
+ "mappings": "AAAA,SAAS,cAAsC;AAC/C,SAAS,kBAAkB;AAE3B,eAAsB,uBACpB,SACA,OACA,MACiB;AACjB,QAAM,WAAW,MAAM,WAAW,SAAS,QAAQ,oBAAoB;AAAA,IACrE;AAAA,IACA,MAAM,EAAE,MAAM,QAAQ,WAAW,KAAK,IAAI,CAAC,GAAG;AAAA,EAChD,CAAC;AACD,SAAO,SAAS,GAAG,GAAG,wCAAwC,SAAS,OAAO,CAAC,EAAE,EAAE,WAAW;AAC9F,QAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,SAAO,OAAO,KAAK,OAAO,YAAY,KAAK,GAAG,SAAS,CAAC,EAAE,WAAW;AACrE,SAAO,KAAK;AACd;AAEA,eAAsB,6BACpB,SACA,OACA,OACiB;AACjB,QAAM,WAAW,MAAM,WAAW,SAAS,QAAQ,2BAA2B;AAAA,IAC5E;AAAA,IACA,MAAM,EAAE,aAAa,OAAO,eAAe,aAAa,KAAK,IAAI,CAAC,GAAG;AAAA,EACvE,CAAC;AACD,SAAO,SAAS,GAAG,GAAG,+CAA+C,SAAS,OAAO,CAAC,EAAE,EAAE,WAAW;AACrG,QAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,SAAO,OAAO,KAAK,OAAO,YAAY,KAAK,GAAG,SAAS,CAAC,EAAE,WAAW;AACrE,SAAO,KAAK;AACd;AAEA,eAAsB,2BACpB,SACA,OACA,OACiB;AACjB,QAAM,WAAW,MAAM,WAAW,SAAS,QAAQ,yBAAyB;AAAA,IAC1E;AAAA,IACA,MAAM,EAAE,MAAM,OAAO,QAAQ,WAAW,KAAK,IAAI,CAAC,GAAG;AAAA,EACvD,CAAC;AACD,SAAO,SAAS,GAAG,GAAG,6CAA6C,SAAS,OAAO,CAAC,EAAE,EAAE,WAAW;AACnG,QAAM,OAAQ,MAAM,SAAS,KAAK;AAClC,SAAO,OAAO,KAAK,OAAO,YAAY,KAAK,GAAG,SAAS,CAAC,EAAE,WAAW;AACrE,SAAO,KAAK;AACd;AAEA,eAAsB,0BACpB,SACA,OACA,MACA,IACe;AACf,MAAI,CAAC,SAAS,CAAC,GAAI;AACnB,MAAI;AACF,UAAM,WAAW,SAAS,UAAU,GAAG,IAAI,OAAO,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC;AAAA,EACvF,QAAQ;AACN;AAAA,EACF;AACF;",
6
+ "names": []
7
+ }
@@ -301,20 +301,30 @@ async function ensureDefaultRoleAcls(em, tenantId, modules, options = {}) {
301
301
  const superadminRole = includeSuperadminRole ? await findRoleByName(em, "superadmin", roleTenantId) : null;
302
302
  const adminRole = await findRoleByName(em, "admin", roleTenantId);
303
303
  const employeeRole = await findRoleByName(em, "employee", roleTenantId);
304
+ const builtInRoles = ["superadmin", "admin", "employee"];
304
305
  const superadminFeatures = [];
305
306
  const adminFeatures = [];
306
307
  const employeeFeatures = [];
308
+ const customRoleFeatures = /* @__PURE__ */ new Map();
307
309
  for (const mod of modules) {
308
310
  const roleFeatures = mod.setup?.defaultRoleFeatures;
309
311
  if (!roleFeatures) continue;
310
312
  if (roleFeatures.superadmin) superadminFeatures.push(...roleFeatures.superadmin);
311
313
  if (roleFeatures.admin) adminFeatures.push(...roleFeatures.admin);
312
314
  if (roleFeatures.employee) employeeFeatures.push(...roleFeatures.employee);
315
+ for (const [roleName, features] of Object.entries(roleFeatures)) {
316
+ if (builtInRoles.includes(roleName)) continue;
317
+ if (!Array.isArray(features)) continue;
318
+ const existing = customRoleFeatures.get(roleName) ?? [];
319
+ existing.push(...features);
320
+ customRoleFeatures.set(roleName, existing);
321
+ }
313
322
  }
314
323
  console.log("\u2705 Seeded default role features", {
315
324
  superadmin: superadminFeatures,
316
325
  admin: adminFeatures,
317
- employee: employeeFeatures
326
+ employee: employeeFeatures,
327
+ ...customRoleFeatures.size > 0 ? Object.fromEntries(customRoleFeatures) : {}
318
328
  });
319
329
  if (includeSuperadminRole && superadminRole) {
320
330
  await ensureRoleAclFor(em, superadminRole, tenantId, superadminFeatures, { isSuperAdmin: true });
@@ -325,6 +335,12 @@ async function ensureDefaultRoleAcls(em, tenantId, modules, options = {}) {
325
335
  if (employeeRole) {
326
336
  await ensureRoleAclFor(em, employeeRole, tenantId, employeeFeatures);
327
337
  }
338
+ for (const [roleName, features] of customRoleFeatures) {
339
+ const role = await findRoleByName(em, roleName, roleTenantId);
340
+ if (role) {
341
+ await ensureRoleAclFor(em, role, tenantId, features);
342
+ }
343
+ }
328
344
  }
329
345
  async function ensureRoleAclFor(em, role, tenantId, features, options = {}) {
330
346
  const existing = await em.findOne(RoleAcl, { role, tenantId });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/auth/lib/setup-app.ts"],
4
- "sourcesContent": ["import { hash } from 'bcryptjs'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { Role, RoleAcl, User, UserRole } from '@open-mercato/core/modules/auth/data/entities'\nimport { Tenant, Organization } from '@open-mercato/core/modules/directory/data/entities'\nimport { rebuildHierarchyForTenant } from '@open-mercato/core/modules/directory/lib/hierarchy'\nimport { normalizeTenantId } from './tenantAccess'\nimport { computeEmailHash } from '@open-mercato/core/modules/auth/lib/emailHash'\nimport type { Module } from '@open-mercato/shared/modules/registry'\nimport { isEncryptionDebugEnabled, isTenantDataEncryptionEnabled } from '@open-mercato/shared/lib/encryption/toggles'\nimport { EncryptionMap } from '@open-mercato/core/modules/entities/data/entities'\nimport { DEFAULT_ENCRYPTION_MAPS } from '@open-mercato/core/modules/entities/lib/encryptionDefaults'\nimport { createKmsService } from '@open-mercato/shared/lib/encryption/kms'\nimport { TenantDataEncryptionService } from '@open-mercato/shared/lib/encryption/tenantDataEncryptionService'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\n\nconst DEFAULT_ROLE_NAMES = ['employee', 'admin', 'superadmin'] as const\nconst DEMO_SUPERADMIN_EMAIL = 'superadmin@acme.com'\nconst DEFAULT_DERIVED_EMAIL_DOMAIN = DEMO_SUPERADMIN_EMAIL.split('@')[1] ?? 'acme.com'\n\nexport type EnsureRolesOptions = {\n roleNames?: string[]\n tenantId?: string | null\n}\n\nasync function ensureRolesInContext(\n em: EntityManager,\n roleNames: string[],\n tenantId: string | null,\n) {\n for (const name of roleNames) {\n const existing = await em.findOne(Role, { name, tenantId })\n if (existing) continue\n if (tenantId !== null) {\n const globalRole = await em.findOne(Role, { name, tenantId: null })\n if (globalRole) {\n globalRole.tenantId = tenantId\n em.persist(globalRole)\n continue\n }\n }\n em.persist(em.create(Role, { name, tenantId, createdAt: new Date() }))\n }\n}\n\nexport async function ensureRoles(em: EntityManager, options: EnsureRolesOptions = {}) {\n const roleNames = options.roleNames ?? [...DEFAULT_ROLE_NAMES]\n const tenantId = normalizeTenantId(options.tenantId ?? null) ?? null\n await em.transactional(async (tem) => {\n await ensureRolesInContext(tem, roleNames, tenantId)\n await tem.flush()\n })\n}\n\nasync function findRoleByName(\n em: EntityManager,\n name: string,\n tenantId: string | null,\n): Promise<Role | null> {\n const normalizedTenant = normalizeTenantId(tenantId ?? null) ?? null\n let role = await em.findOne(Role, { name, tenantId: normalizedTenant })\n if (!role && normalizedTenant !== null) {\n role = await em.findOne(Role, { name, tenantId: null })\n }\n return role\n}\n\nasync function findRoleByNameOrFail(\n em: EntityManager,\n name: string,\n tenantId: string | null,\n): Promise<Role> {\n const role = await findRoleByName(em, name, tenantId)\n if (!role) throw new Error(`ROLE_NOT_FOUND:${name}`)\n return role\n}\n\ntype PrimaryUserInput = {\n email: string\n password?: string\n hashedPassword?: string | null\n firstName?: string | null\n lastName?: string | null\n displayName?: string | null\n confirm?: boolean\n}\n\nconst DERIVED_EMAIL_ENV = {\n admin: 'OM_INIT_ADMIN_EMAIL',\n employee: 'OM_INIT_EMPLOYEE_EMAIL',\n} as const\n\nexport type SetupInitialTenantOptions = {\n orgName: string\n primaryUser: PrimaryUserInput\n roleNames?: string[]\n includeDerivedUsers?: boolean\n failIfUserExists?: boolean\n primaryUserRoles?: string[]\n includeSuperadminRole?: boolean\n /** Optional list of enabled modules. When provided, module setup hooks are called. */\n modules?: Module[]\n}\n\nexport type SetupInitialTenantResult = {\n tenantId: string\n organizationId: string\n users: Array<{ user: User; roles: string[]; created: boolean }>\n reusedExistingUser: boolean\n}\n\nexport async function setupInitialTenant(\n em: EntityManager,\n options: SetupInitialTenantOptions,\n): Promise<SetupInitialTenantResult> {\n const {\n primaryUser,\n includeDerivedUsers = true,\n failIfUserExists = false,\n primaryUserRoles,\n includeSuperadminRole = true,\n } = options\n const primaryRolesInput = primaryUserRoles && primaryUserRoles.length ? primaryUserRoles : ['superadmin']\n const primaryRoles = includeSuperadminRole\n ? primaryRolesInput\n : primaryRolesInput.filter((role) => role !== 'superadmin')\n if (primaryRoles.length === 0) {\n throw new Error('PRIMARY_ROLES_REQUIRED')\n }\n const defaultRoleNames = options.roleNames ?? [...DEFAULT_ROLE_NAMES]\n const resolvedRoleNames = includeSuperadminRole\n ? defaultRoleNames\n : defaultRoleNames.filter((role) => role !== 'superadmin')\n const roleNames = Array.from(new Set([...resolvedRoleNames, ...primaryRoles]))\n\n const mainEmail = primaryUser.email\n const existingUser = await em.findOne(User, { email: mainEmail })\n if (existingUser && failIfUserExists) {\n throw new Error('USER_EXISTS')\n }\n\n let tenantId: string | undefined\n let organizationId: string | undefined\n let reusedExistingUser = false\n const userSnapshots: Array<{ user: User; roles: string[]; created: boolean }> = []\n\n await em.transactional(async (tem) => {\n if (!existingUser) return\n reusedExistingUser = true\n tenantId = existingUser.tenantId ? String(existingUser.tenantId) : undefined\n organizationId = existingUser.organizationId ? String(existingUser.organizationId) : undefined\n const roleTenantId = normalizeTenantId(existingUser.tenantId ?? null) ?? null\n\n await ensureRolesInContext(tem, roleNames, roleTenantId)\n await tem.flush()\n\n const requiredRoleSet = new Set([...roleNames, ...primaryRoles])\n const links = await findWithDecryption(\n tem,\n UserRole,\n { user: existingUser },\n { populate: ['role'] },\n { tenantId: roleTenantId, organizationId: null },\n )\n const currentRoles = new Set(links.map((link) => link.role.name))\n for (const roleName of requiredRoleSet) {\n if (!currentRoles.has(roleName)) {\n const role = await findRoleByNameOrFail(tem, roleName, roleTenantId)\n tem.persist(tem.create(UserRole, { user: existingUser, role, createdAt: new Date() }))\n }\n }\n await tem.flush()\n const roles = Array.from(new Set([...currentRoles, ...roleNames]))\n userSnapshots.push({ user: existingUser, roles, created: false })\n })\n\n if (!existingUser) {\n const baseUsers: Array<{\n email: string\n roles: string[]\n name?: string | null\n passwordHash?: string | null\n }> = [\n { email: primaryUser.email, roles: primaryRoles, name: resolvePrimaryName(primaryUser) },\n ]\n if (includeDerivedUsers) {\n const adminOverride = readEnvValue(DERIVED_EMAIL_ENV.admin)\n const employeeOverride = readEnvValue(DERIVED_EMAIL_ENV.employee)\n const adminEmail = adminOverride ?? `admin@${DEFAULT_DERIVED_EMAIL_DOMAIN}`\n const employeeEmail = employeeOverride ?? `employee@${DEFAULT_DERIVED_EMAIL_DOMAIN}`\n const adminPassword = readEnvValue('OM_INIT_ADMIN_PASSWORD') || 'secret'\n const employeePassword = readEnvValue('OM_INIT_EMPLOYEE_PASSWORD') || 'secret'\n const adminPasswordHash = adminPassword ? await resolvePasswordHash({ email: adminEmail, password: adminPassword }) : null\n const employeePasswordHash = employeePassword\n ? await resolvePasswordHash({ email: employeeEmail, password: employeePassword })\n : null\n addUniqueBaseUser(baseUsers, { email: adminEmail, roles: ['admin'], passwordHash: adminPasswordHash })\n addUniqueBaseUser(baseUsers, { email: employeeEmail, roles: ['employee'], passwordHash: employeePasswordHash })\n }\n const passwordHash = await resolvePasswordHash(primaryUser)\n\n await em.transactional(async (tem) => {\n const tenant = tem.create(Tenant, {\n name: `${options.orgName} Tenant`,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n tem.persist(tenant)\n await tem.flush()\n\n const organization = tem.create(Organization, {\n name: options.orgName,\n tenant,\n isActive: true,\n depth: 0,\n ancestorIds: [],\n childIds: [],\n descendantIds: [],\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n tem.persist(organization)\n await tem.flush()\n\n tenantId = String(tenant.id)\n organizationId = String(organization.id)\n const roleTenantId = tenantId\n\n if (isTenantDataEncryptionEnabled()) {\n try {\n const kms = createKmsService()\n if (kms.isHealthy()) {\n if (isEncryptionDebugEnabled()) {\n console.info('\uD83D\uDD11 [encryption][setup] provisioning tenant DEK', { tenantId: String(tenant.id) })\n }\n await kms.createTenantDek(String(tenant.id))\n if (isEncryptionDebugEnabled()) {\n console.info('\uD83D\uDD11 [encryption][setup] created tenant DEK during setup', { tenantId: String(tenant.id) })\n }\n } else {\n if (isEncryptionDebugEnabled()) {\n console.warn('\u26A0\uFE0F [encryption][setup] KMS not healthy, skipping tenant DEK creation', { tenantId: String(tenant.id) })\n }\n }\n } catch (err) {\n if (isEncryptionDebugEnabled()) {\n console.warn('\u26A0\uFE0F [encryption][setup] Failed to create tenant DEK', err)\n }\n }\n }\n\n await ensureRolesInContext(tem, roleNames, roleTenantId)\n await tem.flush()\n\n if (isTenantDataEncryptionEnabled()) {\n for (const spec of DEFAULT_ENCRYPTION_MAPS) {\n const existing = await tem.findOne(EncryptionMap, { entityId: spec.entityId, tenantId: tenant.id, organizationId: organization.id, deletedAt: null })\n if (!existing) {\n tem.persist(tem.create(EncryptionMap, {\n entityId: spec.entityId,\n tenantId: tenant.id,\n organizationId: organization.id,\n fieldsJson: spec.fields,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n }))\n } else {\n existing.fieldsJson = spec.fields\n existing.isActive = true\n }\n }\n await tem.flush()\n }\n })\n\n await em.transactional(async (tem) => {\n if (!tenantId || !organizationId) return\n const roleTenantId = tenantId\n const encryptionService = isTenantDataEncryptionEnabled()\n ? new TenantDataEncryptionService(tem as any, { kms: createKmsService() })\n : null\n if (encryptionService) {\n await encryptionService.invalidateMap('auth:user', String(tenantId), String(organizationId))\n await encryptionService.invalidateMap('auth:user', String(tenantId), null)\n }\n\n for (const base of baseUsers) {\n const resolvedPasswordHash = base.passwordHash ?? passwordHash\n let user = await tem.findOne(User, { email: base.email })\n const confirm = primaryUser.confirm ?? true\n const encryptedPayload = encryptionService\n ? await encryptionService.encryptEntityPayload('auth:user', { email: base.email }, tenantId, organizationId)\n : { email: base.email, emailHash: computeEmailHash(base.email) }\n if (user) {\n user.passwordHash = resolvedPasswordHash\n user.organizationId = organizationId\n user.tenantId = tenantId\n if (isTenantDataEncryptionEnabled()) {\n user.email = encryptedPayload.email as any\n user.emailHash = (encryptedPayload as any).emailHash ?? computeEmailHash(base.email)\n }\n if (base.name) user.name = base.name\n if (confirm) user.isConfirmed = true\n tem.persist(user)\n userSnapshots.push({ user, roles: base.roles, created: false })\n } else {\n user = tem.create(User, {\n email: (encryptedPayload as any).email ?? base.email,\n emailHash: isTenantDataEncryptionEnabled() ? (encryptedPayload as any).emailHash ?? computeEmailHash(base.email) : undefined,\n passwordHash: resolvedPasswordHash,\n organizationId,\n tenantId,\n name: base.name ?? undefined,\n isConfirmed: confirm,\n createdAt: new Date(),\n })\n tem.persist(user)\n userSnapshots.push({ user, roles: base.roles, created: true })\n }\n await tem.flush()\n for (const roleName of base.roles) {\n const role = await findRoleByNameOrFail(tem, roleName, roleTenantId)\n const existingLink = await tem.findOne(UserRole, { user, role })\n if (!existingLink) tem.persist(tem.create(UserRole, { user, role, createdAt: new Date() }))\n }\n await tem.flush()\n }\n })\n }\n\n if (!tenantId || !organizationId) {\n throw new Error('SETUP_FAILED')\n }\n\n if (!reusedExistingUser) {\n await rebuildHierarchyForTenant(em, tenantId)\n }\n\n const resolvedModules = options.modules ?? tryGetModules()\n await ensureDefaultRoleAcls(em, tenantId, resolvedModules, { includeSuperadminRole })\n await deactivateDemoSuperAdminIfSelfOnboardingEnabled(em)\n\n // Call module onTenantCreated hooks\n for (const mod of resolvedModules) {\n if (mod.setup?.onTenantCreated) {\n await mod.setup.onTenantCreated({ em, tenantId, organizationId })\n }\n }\n\n return {\n tenantId,\n organizationId,\n users: userSnapshots,\n reusedExistingUser,\n }\n}\n\nfunction resolvePrimaryName(input: PrimaryUserInput): string | null {\n if (input.displayName && input.displayName.trim()) return input.displayName.trim()\n const parts = [input.firstName, input.lastName].map((value) => value?.trim()).filter(Boolean)\n if (parts.length) return parts.join(' ')\n return null\n}\n\nfunction readEnvValue(key: string): string | undefined {\n const value = process.env[key]\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : undefined\n}\n\nfunction addUniqueBaseUser(\n baseUsers: Array<{ email: string; roles: string[]; name?: string | null; passwordHash?: string | null }>,\n entry: { email: string; roles: string[]; name?: string | null; passwordHash?: string | null },\n) {\n if (!entry.email) return\n const normalized = entry.email.toLowerCase()\n if (baseUsers.some((user) => user.email.toLowerCase() === normalized)) return\n baseUsers.push(entry)\n}\n\nfunction isDemoModeEnabled(): boolean {\n const parsed = parseBooleanToken(process.env.DEMO_MODE ?? '')\n return parsed === false ? false : true\n}\n\nfunction shouldKeepDemoSuperadminDuringInit(): boolean {\n if (process.env.OM_INIT_FLOW !== 'true') return false\n if (!readEnvValue('OM_INIT_SUPERADMIN_EMAIL')) return false\n return isDemoModeEnabled()\n}\n\nasync function resolvePasswordHash(input: PrimaryUserInput): Promise<string | null> {\n if (typeof input.hashedPassword === 'string') return input.hashedPassword\n if (input.password) return hash(input.password, 10)\n return null\n}\n\nasync function ensureDefaultRoleAcls(\n em: EntityManager,\n tenantId: string,\n modules: Module[],\n options: { includeSuperadminRole?: boolean } = {},\n) {\n const includeSuperadminRole = options.includeSuperadminRole ?? true\n const roleTenantId = normalizeTenantId(tenantId) ?? null\n const superadminRole = includeSuperadminRole ? await findRoleByName(em, 'superadmin', roleTenantId) : null\n const adminRole = await findRoleByName(em, 'admin', roleTenantId)\n const employeeRole = await findRoleByName(em, 'employee', roleTenantId)\n\n // Merge features from all enabled modules' setup configs\n const superadminFeatures: string[] = []\n const adminFeatures: string[] = []\n const employeeFeatures: string[] = []\n\n for (const mod of modules) {\n const roleFeatures = mod.setup?.defaultRoleFeatures\n if (!roleFeatures) continue\n if (roleFeatures.superadmin) superadminFeatures.push(...roleFeatures.superadmin)\n if (roleFeatures.admin) adminFeatures.push(...roleFeatures.admin)\n if (roleFeatures.employee) employeeFeatures.push(...roleFeatures.employee)\n }\n\n console.log('\u2705 Seeded default role features', {\n superadmin: superadminFeatures,\n admin: adminFeatures,\n employee: employeeFeatures,\n })\n\n if (includeSuperadminRole && superadminRole) {\n await ensureRoleAclFor(em, superadminRole, tenantId, superadminFeatures, { isSuperAdmin: true })\n }\n if (adminRole) {\n await ensureRoleAclFor(em, adminRole, tenantId, adminFeatures)\n }\n if (employeeRole) {\n await ensureRoleAclFor(em, employeeRole, tenantId, employeeFeatures)\n }\n}\n\nasync function ensureRoleAclFor(\n em: EntityManager,\n role: Role,\n tenantId: string,\n features: string[],\n options: { isSuperAdmin?: boolean } = {},\n) {\n const existing = await em.findOne(RoleAcl, { role, tenantId })\n if (!existing) {\n const acl = em.create(RoleAcl, {\n role,\n tenantId,\n featuresJson: features,\n isSuperAdmin: !!options.isSuperAdmin,\n createdAt: new Date(),\n })\n await em.persistAndFlush(acl)\n return\n }\n const currentFeatures = Array.isArray(existing.featuresJson) ? existing.featuresJson : []\n const merged = Array.from(new Set([...currentFeatures, ...features]))\n const changed =\n merged.length !== currentFeatures.length ||\n merged.some((value, index) => value !== currentFeatures[index])\n if (changed) existing.featuresJson = merged\n if (options.isSuperAdmin && !existing.isSuperAdmin) {\n existing.isSuperAdmin = true\n }\n if (changed || options.isSuperAdmin) {\n await em.persistAndFlush(existing)\n }\n}\n\nasync function deactivateDemoSuperAdminIfSelfOnboardingEnabled(em: EntityManager) {\n if (process.env.SELF_SERVICE_ONBOARDING_ENABLED !== 'true') return\n if (shouldKeepDemoSuperadminDuringInit()) return\n try {\n const user = await em.findOne(User, { email: DEMO_SUPERADMIN_EMAIL })\n if (!user) return\n let dirty = false\n if (user.passwordHash) {\n user.passwordHash = null\n dirty = true\n }\n if (user.isConfirmed !== false) {\n user.isConfirmed = false\n dirty = true\n }\n if (dirty) {\n await em.persistAndFlush(user)\n }\n } catch (error) {\n console.error('[auth.setup] failed to deactivate demo superadmin user', error)\n }\n}\n\n/** Try to get modules from runtime registry; returns empty array if not yet registered. */\nfunction tryGetModules(): Module[] {\n try {\n const { getModules } = require('@open-mercato/shared/lib/modules/registry')\n return getModules()\n } catch {\n return []\n }\n}\n"],
5
- "mappings": "AAAA,SAAS,YAAY;AAErB,SAAS,MAAM,SAAS,MAAM,gBAAgB;AAC9C,SAAS,QAAQ,oBAAoB;AACrC,SAAS,iCAAiC;AAC1C,SAAS,yBAAyB;AAClC,SAAS,wBAAwB;AAEjC,SAAS,0BAA0B,qCAAqC;AACxE,SAAS,qBAAqB;AAC9B,SAAS,+BAA+B;AACxC,SAAS,wBAAwB;AACjC,SAAS,mCAAmC;AAC5C,SAAS,0BAA0B;AACnC,SAAS,yBAAyB;AAElC,MAAM,qBAAqB,CAAC,YAAY,SAAS,YAAY;AAC7D,MAAM,wBAAwB;AAC9B,MAAM,+BAA+B,sBAAsB,MAAM,GAAG,EAAE,CAAC,KAAK;AAO5E,eAAe,qBACb,IACA,WACA,UACA;AACA,aAAW,QAAQ,WAAW;AAC5B,UAAM,WAAW,MAAM,GAAG,QAAQ,MAAM,EAAE,MAAM,SAAS,CAAC;AAC1D,QAAI,SAAU;AACd,QAAI,aAAa,MAAM;AACrB,YAAM,aAAa,MAAM,GAAG,QAAQ,MAAM,EAAE,MAAM,UAAU,KAAK,CAAC;AAClE,UAAI,YAAY;AACd,mBAAW,WAAW;AACtB,WAAG,QAAQ,UAAU;AACrB;AAAA,MACF;AAAA,IACF;AACA,OAAG,QAAQ,GAAG,OAAO,MAAM,EAAE,MAAM,UAAU,WAAW,oBAAI,KAAK,EAAE,CAAC,CAAC;AAAA,EACvE;AACF;AAEA,eAAsB,YAAY,IAAmB,UAA8B,CAAC,GAAG;AACrF,QAAM,YAAY,QAAQ,aAAa,CAAC,GAAG,kBAAkB;AAC7D,QAAM,WAAW,kBAAkB,QAAQ,YAAY,IAAI,KAAK;AAChE,QAAM,GAAG,cAAc,OAAO,QAAQ;AACpC,UAAM,qBAAqB,KAAK,WAAW,QAAQ;AACnD,UAAM,IAAI,MAAM;AAAA,EAClB,CAAC;AACH;AAEA,eAAe,eACb,IACA,MACA,UACsB;AACtB,QAAM,mBAAmB,kBAAkB,YAAY,IAAI,KAAK;AAChE,MAAI,OAAO,MAAM,GAAG,QAAQ,MAAM,EAAE,MAAM,UAAU,iBAAiB,CAAC;AACtE,MAAI,CAAC,QAAQ,qBAAqB,MAAM;AACtC,WAAO,MAAM,GAAG,QAAQ,MAAM,EAAE,MAAM,UAAU,KAAK,CAAC;AAAA,EACxD;AACA,SAAO;AACT;AAEA,eAAe,qBACb,IACA,MACA,UACe;AACf,QAAM,OAAO,MAAM,eAAe,IAAI,MAAM,QAAQ;AACpD,MAAI,CAAC,KAAM,OAAM,IAAI,MAAM,kBAAkB,IAAI,EAAE;AACnD,SAAO;AACT;AAYA,MAAM,oBAAoB;AAAA,EACxB,OAAO;AAAA,EACP,UAAU;AACZ;AAqBA,eAAsB,mBACpB,IACA,SACmC;AACnC,QAAM;AAAA,IACJ;AAAA,IACA,sBAAsB;AAAA,IACtB,mBAAmB;AAAA,IACnB;AAAA,IACA,wBAAwB;AAAA,EAC1B,IAAI;AACJ,QAAM,oBAAoB,oBAAoB,iBAAiB,SAAS,mBAAmB,CAAC,YAAY;AACxG,QAAM,eAAe,wBACjB,oBACA,kBAAkB,OAAO,CAAC,SAAS,SAAS,YAAY;AAC5D,MAAI,aAAa,WAAW,GAAG;AAC7B,UAAM,IAAI,MAAM,wBAAwB;AAAA,EAC1C;AACA,QAAM,mBAAmB,QAAQ,aAAa,CAAC,GAAG,kBAAkB;AACpE,QAAM,oBAAoB,wBACtB,mBACA,iBAAiB,OAAO,CAAC,SAAS,SAAS,YAAY;AAC3D,QAAM,YAAY,MAAM,KAAK,oBAAI,IAAI,CAAC,GAAG,mBAAmB,GAAG,YAAY,CAAC,CAAC;AAE7E,QAAM,YAAY,YAAY;AAC9B,QAAM,eAAe,MAAM,GAAG,QAAQ,MAAM,EAAE,OAAO,UAAU,CAAC;AAChE,MAAI,gBAAgB,kBAAkB;AACpC,UAAM,IAAI,MAAM,aAAa;AAAA,EAC/B;AAEA,MAAI;AACJ,MAAI;AACJ,MAAI,qBAAqB;AACzB,QAAM,gBAA0E,CAAC;AAEjF,QAAM,GAAG,cAAc,OAAO,QAAQ;AACpC,QAAI,CAAC,aAAc;AACnB,yBAAqB;AACrB,eAAW,aAAa,WAAW,OAAO,aAAa,QAAQ,IAAI;AACnE,qBAAiB,aAAa,iBAAiB,OAAO,aAAa,cAAc,IAAI;AACrF,UAAM,eAAe,kBAAkB,aAAa,YAAY,IAAI,KAAK;AAEzE,UAAM,qBAAqB,KAAK,WAAW,YAAY;AACvD,UAAM,IAAI,MAAM;AAEhB,UAAM,kBAAkB,oBAAI,IAAI,CAAC,GAAG,WAAW,GAAG,YAAY,CAAC;AAC/D,UAAM,QAAQ,MAAM;AAAA,MAClB;AAAA,MACA;AAAA,MACA,EAAE,MAAM,aAAa;AAAA,MACrB,EAAE,UAAU,CAAC,MAAM,EAAE;AAAA,MACrB,EAAE,UAAU,cAAc,gBAAgB,KAAK;AAAA,IACjD;AACA,UAAM,eAAe,IAAI,IAAI,MAAM,IAAI,CAAC,SAAS,KAAK,KAAK,IAAI,CAAC;AAChE,eAAW,YAAY,iBAAiB;AACtC,UAAI,CAAC,aAAa,IAAI,QAAQ,GAAG;AAC/B,cAAM,OAAO,MAAM,qBAAqB,KAAK,UAAU,YAAY;AACnE,YAAI,QAAQ,IAAI,OAAO,UAAU,EAAE,MAAM,cAAc,MAAM,WAAW,oBAAI,KAAK,EAAE,CAAC,CAAC;AAAA,MACvF;AAAA,IACF;AACA,UAAM,IAAI,MAAM;AAChB,UAAM,QAAQ,MAAM,KAAK,oBAAI,IAAI,CAAC,GAAG,cAAc,GAAG,SAAS,CAAC,CAAC;AACjE,kBAAc,KAAK,EAAE,MAAM,cAAc,OAAO,SAAS,MAAM,CAAC;AAAA,EAClE,CAAC;AAED,MAAI,CAAC,cAAc;AACjB,UAAM,YAKD;AAAA,MACH,EAAE,OAAO,YAAY,OAAO,OAAO,cAAc,MAAM,mBAAmB,WAAW,EAAE;AAAA,IACzF;AACA,QAAI,qBAAqB;AACvB,YAAM,gBAAgB,aAAa,kBAAkB,KAAK;AAC1D,YAAM,mBAAmB,aAAa,kBAAkB,QAAQ;AAChE,YAAM,aAAa,iBAAiB,SAAS,4BAA4B;AACzE,YAAM,gBAAgB,oBAAoB,YAAY,4BAA4B;AAClF,YAAM,gBAAgB,aAAa,wBAAwB,KAAK;AAChE,YAAM,mBAAmB,aAAa,2BAA2B,KAAK;AACtE,YAAM,oBAAoB,gBAAgB,MAAM,oBAAoB,EAAE,OAAO,YAAY,UAAU,cAAc,CAAC,IAAI;AACtH,YAAM,uBAAuB,mBACzB,MAAM,oBAAoB,EAAE,OAAO,eAAe,UAAU,iBAAiB,CAAC,IAC9E;AACJ,wBAAkB,WAAW,EAAE,OAAO,YAAY,OAAO,CAAC,OAAO,GAAG,cAAc,kBAAkB,CAAC;AACrG,wBAAkB,WAAW,EAAE,OAAO,eAAe,OAAO,CAAC,UAAU,GAAG,cAAc,qBAAqB,CAAC;AAAA,IAChH;AACA,UAAM,eAAe,MAAM,oBAAoB,WAAW;AAE1D,UAAM,GAAG,cAAc,OAAO,QAAQ;AACpC,YAAM,SAAS,IAAI,OAAO,QAAQ;AAAA,QAChC,MAAM,GAAG,QAAQ,OAAO;AAAA,QACxB,UAAU;AAAA,QACV,WAAW,oBAAI,KAAK;AAAA,QACpB,WAAW,oBAAI,KAAK;AAAA,MACtB,CAAC;AACD,UAAI,QAAQ,MAAM;AAClB,YAAM,IAAI,MAAM;AAEhB,YAAM,eAAe,IAAI,OAAO,cAAc;AAAA,QAC5C,MAAM,QAAQ;AAAA,QACd;AAAA,QACA,UAAU;AAAA,QACV,OAAO;AAAA,QACP,aAAa,CAAC;AAAA,QACd,UAAU,CAAC;AAAA,QACX,eAAe,CAAC;AAAA,QAChB,WAAW,oBAAI,KAAK;AAAA,QACpB,WAAW,oBAAI,KAAK;AAAA,MACtB,CAAC;AACD,UAAI,QAAQ,YAAY;AACxB,YAAM,IAAI,MAAM;AAEhB,iBAAW,OAAO,OAAO,EAAE;AAC3B,uBAAiB,OAAO,aAAa,EAAE;AACvC,YAAM,eAAe;AAErB,UAAI,8BAA8B,GAAG;AACnC,YAAI;AACF,gBAAM,MAAM,iBAAiB;AAC7B,cAAI,IAAI,UAAU,GAAG;AACnB,gBAAI,yBAAyB,GAAG;AAC9B,sBAAQ,KAAK,yDAAkD,EAAE,UAAU,OAAO,OAAO,EAAE,EAAE,CAAC;AAAA,YAChG;AACA,kBAAM,IAAI,gBAAgB,OAAO,OAAO,EAAE,CAAC;AAC3C,gBAAI,yBAAyB,GAAG;AAC9B,sBAAQ,KAAK,iEAA0D,EAAE,UAAU,OAAO,OAAO,EAAE,EAAE,CAAC;AAAA,YACxG;AAAA,UACF,OAAO;AACL,gBAAI,yBAAyB,GAAG;AAC9B,sBAAQ,KAAK,kFAAwE,EAAE,UAAU,OAAO,OAAO,EAAE,EAAE,CAAC;AAAA,YACtH;AAAA,UACF;AAAA,QACF,SAAS,KAAK;AACZ,cAAI,yBAAyB,GAAG;AAC9B,oBAAQ,KAAK,gEAAsD,GAAG;AAAA,UACxE;AAAA,QACF;AAAA,MACF;AAEA,YAAM,qBAAqB,KAAK,WAAW,YAAY;AACvD,YAAM,IAAI,MAAM;AAEhB,UAAI,8BAA8B,GAAG;AACnC,mBAAW,QAAQ,yBAAyB;AAC1C,gBAAM,WAAW,MAAM,IAAI,QAAQ,eAAe,EAAE,UAAU,KAAK,UAAU,UAAU,OAAO,IAAI,gBAAgB,aAAa,IAAI,WAAW,KAAK,CAAC;AACpJ,cAAI,CAAC,UAAU;AACb,gBAAI,QAAQ,IAAI,OAAO,eAAe;AAAA,cACpC,UAAU,KAAK;AAAA,cACf,UAAU,OAAO;AAAA,cACjB,gBAAgB,aAAa;AAAA,cAC7B,YAAY,KAAK;AAAA,cACjB,UAAU;AAAA,cACV,WAAW,oBAAI,KAAK;AAAA,cACpB,WAAW,oBAAI,KAAK;AAAA,YACtB,CAAC,CAAC;AAAA,UACJ,OAAO;AACL,qBAAS,aAAa,KAAK;AAC3B,qBAAS,WAAW;AAAA,UACtB;AAAA,QACF;AACA,cAAM,IAAI,MAAM;AAAA,MAClB;AAAA,IACF,CAAC;AAED,UAAM,GAAG,cAAc,OAAO,QAAQ;AACpC,UAAI,CAAC,YAAY,CAAC,eAAgB;AAClC,YAAM,eAAe;AACrB,YAAM,oBAAoB,8BAA8B,IACpD,IAAI,4BAA4B,KAAY,EAAE,KAAK,iBAAiB,EAAE,CAAC,IACvE;AACJ,UAAI,mBAAmB;AACrB,cAAM,kBAAkB,cAAc,aAAa,OAAO,QAAQ,GAAG,OAAO,cAAc,CAAC;AAC3F,cAAM,kBAAkB,cAAc,aAAa,OAAO,QAAQ,GAAG,IAAI;AAAA,MAC3E;AAEA,iBAAW,QAAQ,WAAW;AAC5B,cAAM,uBAAuB,KAAK,gBAAgB;AAClD,YAAI,OAAO,MAAM,IAAI,QAAQ,MAAM,EAAE,OAAO,KAAK,MAAM,CAAC;AACxD,cAAM,UAAU,YAAY,WAAW;AACvC,cAAM,mBAAmB,oBACrB,MAAM,kBAAkB,qBAAqB,aAAa,EAAE,OAAO,KAAK,MAAM,GAAG,UAAU,cAAc,IACzG,EAAE,OAAO,KAAK,OAAO,WAAW,iBAAiB,KAAK,KAAK,EAAE;AACjE,YAAI,MAAM;AACR,eAAK,eAAe;AACpB,eAAK,iBAAiB;AACtB,eAAK,WAAW;AAChB,cAAI,8BAA8B,GAAG;AACnC,iBAAK,QAAQ,iBAAiB;AAC9B,iBAAK,YAAa,iBAAyB,aAAa,iBAAiB,KAAK,KAAK;AAAA,UACrF;AACA,cAAI,KAAK,KAAM,MAAK,OAAO,KAAK;AAChC,cAAI,QAAS,MAAK,cAAc;AAChC,cAAI,QAAQ,IAAI;AAChB,wBAAc,KAAK,EAAE,MAAM,OAAO,KAAK,OAAO,SAAS,MAAM,CAAC;AAAA,QAChE,OAAO;AACL,iBAAO,IAAI,OAAO,MAAM;AAAA,YACtB,OAAQ,iBAAyB,SAAS,KAAK;AAAA,YAC/C,WAAW,8BAA8B,IAAK,iBAAyB,aAAa,iBAAiB,KAAK,KAAK,IAAI;AAAA,YACnH,cAAc;AAAA,YACd;AAAA,YACA;AAAA,YACA,MAAM,KAAK,QAAQ;AAAA,YACnB,aAAa;AAAA,YACb,WAAW,oBAAI,KAAK;AAAA,UACtB,CAAC;AACD,cAAI,QAAQ,IAAI;AAChB,wBAAc,KAAK,EAAE,MAAM,OAAO,KAAK,OAAO,SAAS,KAAK,CAAC;AAAA,QAC/D;AACA,cAAM,IAAI,MAAM;AAChB,mBAAW,YAAY,KAAK,OAAO;AACjC,gBAAM,OAAO,MAAM,qBAAqB,KAAK,UAAU,YAAY;AACnE,gBAAM,eAAe,MAAM,IAAI,QAAQ,UAAU,EAAE,MAAM,KAAK,CAAC;AAC/D,cAAI,CAAC,aAAc,KAAI,QAAQ,IAAI,OAAO,UAAU,EAAE,MAAM,MAAM,WAAW,oBAAI,KAAK,EAAE,CAAC,CAAC;AAAA,QAC5F;AACA,cAAM,IAAI,MAAM;AAAA,MAClB;AAAA,IACF,CAAC;AAAA,EACH;AAEA,MAAI,CAAC,YAAY,CAAC,gBAAgB;AAChC,UAAM,IAAI,MAAM,cAAc;AAAA,EAChC;AAEA,MAAI,CAAC,oBAAoB;AACvB,UAAM,0BAA0B,IAAI,QAAQ;AAAA,EAC9C;AAEA,QAAM,kBAAkB,QAAQ,WAAW,cAAc;AACzD,QAAM,sBAAsB,IAAI,UAAU,iBAAiB,EAAE,sBAAsB,CAAC;AACpF,QAAM,gDAAgD,EAAE;AAGxD,aAAW,OAAO,iBAAiB;AACjC,QAAI,IAAI,OAAO,iBAAiB;AAC9B,YAAM,IAAI,MAAM,gBAAgB,EAAE,IAAI,UAAU,eAAe,CAAC;AAAA,IAClE;AAAA,EACF;AAEA,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA,OAAO;AAAA,IACP;AAAA,EACF;AACF;AAEA,SAAS,mBAAmB,OAAwC;AAClE,MAAI,MAAM,eAAe,MAAM,YAAY,KAAK,EAAG,QAAO,MAAM,YAAY,KAAK;AACjF,QAAM,QAAQ,CAAC,MAAM,WAAW,MAAM,QAAQ,EAAE,IAAI,CAAC,UAAU,OAAO,KAAK,CAAC,EAAE,OAAO,OAAO;AAC5F,MAAI,MAAM,OAAQ,QAAO,MAAM,KAAK,GAAG;AACvC,SAAO;AACT;AAEA,SAAS,aAAa,KAAiC;AACrD,QAAM,QAAQ,QAAQ,IAAI,GAAG;AAC7B,MAAI,OAAO,UAAU,SAAU,QAAO;AACtC,QAAM,UAAU,MAAM,KAAK;AAC3B,SAAO,QAAQ,SAAS,IAAI,UAAU;AACxC;AAEA,SAAS,kBACP,WACA,OACA;AACA,MAAI,CAAC,MAAM,MAAO;AAClB,QAAM,aAAa,MAAM,MAAM,YAAY;AAC3C,MAAI,UAAU,KAAK,CAAC,SAAS,KAAK,MAAM,YAAY,MAAM,UAAU,EAAG;AACvE,YAAU,KAAK,KAAK;AACtB;AAEA,SAAS,oBAA6B;AACpC,QAAM,SAAS,kBAAkB,QAAQ,IAAI,aAAa,EAAE;AAC5D,SAAO,WAAW,QAAQ,QAAQ;AACpC;AAEA,SAAS,qCAA8C;AACrD,MAAI,QAAQ,IAAI,iBAAiB,OAAQ,QAAO;AAChD,MAAI,CAAC,aAAa,0BAA0B,EAAG,QAAO;AACtD,SAAO,kBAAkB;AAC3B;AAEA,eAAe,oBAAoB,OAAiD;AAClF,MAAI,OAAO,MAAM,mBAAmB,SAAU,QAAO,MAAM;AAC3D,MAAI,MAAM,SAAU,QAAO,KAAK,MAAM,UAAU,EAAE;AAClD,SAAO;AACT;AAEA,eAAe,sBACb,IACA,UACA,SACA,UAA+C,CAAC,GAChD;AACA,QAAM,wBAAwB,QAAQ,yBAAyB;AAC/D,QAAM,eAAe,kBAAkB,QAAQ,KAAK;AACpD,QAAM,iBAAiB,wBAAwB,MAAM,eAAe,IAAI,cAAc,YAAY,IAAI;AACtG,QAAM,YAAY,MAAM,eAAe,IAAI,SAAS,YAAY;AAChE,QAAM,eAAe,MAAM,eAAe,IAAI,YAAY,YAAY;AAGtE,QAAM,qBAA+B,CAAC;AACtC,QAAM,gBAA0B,CAAC;AACjC,QAAM,mBAA6B,CAAC;AAEpC,aAAW,OAAO,SAAS;AACzB,UAAM,eAAe,IAAI,OAAO;AAChC,QAAI,CAAC,aAAc;AACnB,QAAI,aAAa,WAAY,oBAAmB,KAAK,GAAG,aAAa,UAAU;AAC/E,QAAI,aAAa,MAAO,eAAc,KAAK,GAAG,aAAa,KAAK;AAChE,QAAI,aAAa,SAAU,kBAAiB,KAAK,GAAG,aAAa,QAAQ;AAAA,EAC3E;AAEA,UAAQ,IAAI,uCAAkC;AAAA,IAC5C,YAAY;AAAA,IACZ,OAAO;AAAA,IACP,UAAU;AAAA,EACZ,CAAC;AAED,MAAI,yBAAyB,gBAAgB;AAC3C,UAAM,iBAAiB,IAAI,gBAAgB,UAAU,oBAAoB,EAAE,cAAc,KAAK,CAAC;AAAA,EACjG;AACA,MAAI,WAAW;AACb,UAAM,iBAAiB,IAAI,WAAW,UAAU,aAAa;AAAA,EAC/D;AACA,MAAI,cAAc;AAChB,UAAM,iBAAiB,IAAI,cAAc,UAAU,gBAAgB;AAAA,EACrE;AACF;AAEA,eAAe,iBACb,IACA,MACA,UACA,UACA,UAAsC,CAAC,GACvC;AACA,QAAM,WAAW,MAAM,GAAG,QAAQ,SAAS,EAAE,MAAM,SAAS,CAAC;AAC7D,MAAI,CAAC,UAAU;AACb,UAAM,MAAM,GAAG,OAAO,SAAS;AAAA,MAC7B;AAAA,MACA;AAAA,MACA,cAAc;AAAA,MACd,cAAc,CAAC,CAAC,QAAQ;AAAA,MACxB,WAAW,oBAAI,KAAK;AAAA,IACtB,CAAC;AACD,UAAM,GAAG,gBAAgB,GAAG;AAC5B;AAAA,EACF;AACA,QAAM,kBAAkB,MAAM,QAAQ,SAAS,YAAY,IAAI,SAAS,eAAe,CAAC;AACxF,QAAM,SAAS,MAAM,KAAK,oBAAI,IAAI,CAAC,GAAG,iBAAiB,GAAG,QAAQ,CAAC,CAAC;AACpE,QAAM,UACJ,OAAO,WAAW,gBAAgB,UAClC,OAAO,KAAK,CAAC,OAAO,UAAU,UAAU,gBAAgB,KAAK,CAAC;AAChE,MAAI,QAAS,UAAS,eAAe;AACrC,MAAI,QAAQ,gBAAgB,CAAC,SAAS,cAAc;AAClD,aAAS,eAAe;AAAA,EAC1B;AACA,MAAI,WAAW,QAAQ,cAAc;AACnC,UAAM,GAAG,gBAAgB,QAAQ;AAAA,EACnC;AACF;AAEA,eAAe,gDAAgD,IAAmB;AAChF,MAAI,QAAQ,IAAI,oCAAoC,OAAQ;AAC5D,MAAI,mCAAmC,EAAG;AAC1C,MAAI;AACF,UAAM,OAAO,MAAM,GAAG,QAAQ,MAAM,EAAE,OAAO,sBAAsB,CAAC;AACpE,QAAI,CAAC,KAAM;AACX,QAAI,QAAQ;AACZ,QAAI,KAAK,cAAc;AACrB,WAAK,eAAe;AACpB,cAAQ;AAAA,IACV;AACA,QAAI,KAAK,gBAAgB,OAAO;AAC9B,WAAK,cAAc;AACnB,cAAQ;AAAA,IACV;AACA,QAAI,OAAO;AACT,YAAM,GAAG,gBAAgB,IAAI;AAAA,IAC/B;AAAA,EACF,SAAS,OAAO;AACd,YAAQ,MAAM,0DAA0D,KAAK;AAAA,EAC/E;AACF;AAGA,SAAS,gBAA0B;AACjC,MAAI;AACF,UAAM,EAAE,WAAW,IAAI,QAAQ,2CAA2C;AAC1E,WAAO,WAAW;AAAA,EACpB,QAAQ;AACN,WAAO,CAAC;AAAA,EACV;AACF;",
4
+ "sourcesContent": ["import { hash } from 'bcryptjs'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { Role, RoleAcl, User, UserRole } from '@open-mercato/core/modules/auth/data/entities'\nimport { Tenant, Organization } from '@open-mercato/core/modules/directory/data/entities'\nimport { rebuildHierarchyForTenant } from '@open-mercato/core/modules/directory/lib/hierarchy'\nimport { normalizeTenantId } from './tenantAccess'\nimport { computeEmailHash } from '@open-mercato/core/modules/auth/lib/emailHash'\nimport type { Module } from '@open-mercato/shared/modules/registry'\nimport { isEncryptionDebugEnabled, isTenantDataEncryptionEnabled } from '@open-mercato/shared/lib/encryption/toggles'\nimport { EncryptionMap } from '@open-mercato/core/modules/entities/data/entities'\nimport { DEFAULT_ENCRYPTION_MAPS } from '@open-mercato/core/modules/entities/lib/encryptionDefaults'\nimport { createKmsService } from '@open-mercato/shared/lib/encryption/kms'\nimport { TenantDataEncryptionService } from '@open-mercato/shared/lib/encryption/tenantDataEncryptionService'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { parseBooleanToken } from '@open-mercato/shared/lib/boolean'\n\nconst DEFAULT_ROLE_NAMES = ['employee', 'admin', 'superadmin'] as const\nconst DEMO_SUPERADMIN_EMAIL = 'superadmin@acme.com'\nconst DEFAULT_DERIVED_EMAIL_DOMAIN = DEMO_SUPERADMIN_EMAIL.split('@')[1] ?? 'acme.com'\n\nexport type EnsureRolesOptions = {\n roleNames?: string[]\n tenantId?: string | null\n}\n\nasync function ensureRolesInContext(\n em: EntityManager,\n roleNames: string[],\n tenantId: string | null,\n) {\n for (const name of roleNames) {\n const existing = await em.findOne(Role, { name, tenantId })\n if (existing) continue\n if (tenantId !== null) {\n const globalRole = await em.findOne(Role, { name, tenantId: null })\n if (globalRole) {\n globalRole.tenantId = tenantId\n em.persist(globalRole)\n continue\n }\n }\n em.persist(em.create(Role, { name, tenantId, createdAt: new Date() }))\n }\n}\n\nexport async function ensureRoles(em: EntityManager, options: EnsureRolesOptions = {}) {\n const roleNames = options.roleNames ?? [...DEFAULT_ROLE_NAMES]\n const tenantId = normalizeTenantId(options.tenantId ?? null) ?? null\n await em.transactional(async (tem) => {\n await ensureRolesInContext(tem, roleNames, tenantId)\n await tem.flush()\n })\n}\n\nasync function findRoleByName(\n em: EntityManager,\n name: string,\n tenantId: string | null,\n): Promise<Role | null> {\n const normalizedTenant = normalizeTenantId(tenantId ?? null) ?? null\n let role = await em.findOne(Role, { name, tenantId: normalizedTenant })\n if (!role && normalizedTenant !== null) {\n role = await em.findOne(Role, { name, tenantId: null })\n }\n return role\n}\n\nasync function findRoleByNameOrFail(\n em: EntityManager,\n name: string,\n tenantId: string | null,\n): Promise<Role> {\n const role = await findRoleByName(em, name, tenantId)\n if (!role) throw new Error(`ROLE_NOT_FOUND:${name}`)\n return role\n}\n\ntype PrimaryUserInput = {\n email: string\n password?: string\n hashedPassword?: string | null\n firstName?: string | null\n lastName?: string | null\n displayName?: string | null\n confirm?: boolean\n}\n\nconst DERIVED_EMAIL_ENV = {\n admin: 'OM_INIT_ADMIN_EMAIL',\n employee: 'OM_INIT_EMPLOYEE_EMAIL',\n} as const\n\nexport type SetupInitialTenantOptions = {\n orgName: string\n primaryUser: PrimaryUserInput\n roleNames?: string[]\n includeDerivedUsers?: boolean\n failIfUserExists?: boolean\n primaryUserRoles?: string[]\n includeSuperadminRole?: boolean\n /** Optional list of enabled modules. When provided, module setup hooks are called. */\n modules?: Module[]\n}\n\nexport type SetupInitialTenantResult = {\n tenantId: string\n organizationId: string\n users: Array<{ user: User; roles: string[]; created: boolean }>\n reusedExistingUser: boolean\n}\n\nexport async function setupInitialTenant(\n em: EntityManager,\n options: SetupInitialTenantOptions,\n): Promise<SetupInitialTenantResult> {\n const {\n primaryUser,\n includeDerivedUsers = true,\n failIfUserExists = false,\n primaryUserRoles,\n includeSuperadminRole = true,\n } = options\n const primaryRolesInput = primaryUserRoles && primaryUserRoles.length ? primaryUserRoles : ['superadmin']\n const primaryRoles = includeSuperadminRole\n ? primaryRolesInput\n : primaryRolesInput.filter((role) => role !== 'superadmin')\n if (primaryRoles.length === 0) {\n throw new Error('PRIMARY_ROLES_REQUIRED')\n }\n const defaultRoleNames = options.roleNames ?? [...DEFAULT_ROLE_NAMES]\n const resolvedRoleNames = includeSuperadminRole\n ? defaultRoleNames\n : defaultRoleNames.filter((role) => role !== 'superadmin')\n const roleNames = Array.from(new Set([...resolvedRoleNames, ...primaryRoles]))\n\n const mainEmail = primaryUser.email\n const existingUser = await em.findOne(User, { email: mainEmail })\n if (existingUser && failIfUserExists) {\n throw new Error('USER_EXISTS')\n }\n\n let tenantId: string | undefined\n let organizationId: string | undefined\n let reusedExistingUser = false\n const userSnapshots: Array<{ user: User; roles: string[]; created: boolean }> = []\n\n await em.transactional(async (tem) => {\n if (!existingUser) return\n reusedExistingUser = true\n tenantId = existingUser.tenantId ? String(existingUser.tenantId) : undefined\n organizationId = existingUser.organizationId ? String(existingUser.organizationId) : undefined\n const roleTenantId = normalizeTenantId(existingUser.tenantId ?? null) ?? null\n\n await ensureRolesInContext(tem, roleNames, roleTenantId)\n await tem.flush()\n\n const requiredRoleSet = new Set([...roleNames, ...primaryRoles])\n const links = await findWithDecryption(\n tem,\n UserRole,\n { user: existingUser },\n { populate: ['role'] },\n { tenantId: roleTenantId, organizationId: null },\n )\n const currentRoles = new Set(links.map((link) => link.role.name))\n for (const roleName of requiredRoleSet) {\n if (!currentRoles.has(roleName)) {\n const role = await findRoleByNameOrFail(tem, roleName, roleTenantId)\n tem.persist(tem.create(UserRole, { user: existingUser, role, createdAt: new Date() }))\n }\n }\n await tem.flush()\n const roles = Array.from(new Set([...currentRoles, ...roleNames]))\n userSnapshots.push({ user: existingUser, roles, created: false })\n })\n\n if (!existingUser) {\n const baseUsers: Array<{\n email: string\n roles: string[]\n name?: string | null\n passwordHash?: string | null\n }> = [\n { email: primaryUser.email, roles: primaryRoles, name: resolvePrimaryName(primaryUser) },\n ]\n if (includeDerivedUsers) {\n const adminOverride = readEnvValue(DERIVED_EMAIL_ENV.admin)\n const employeeOverride = readEnvValue(DERIVED_EMAIL_ENV.employee)\n const adminEmail = adminOverride ?? `admin@${DEFAULT_DERIVED_EMAIL_DOMAIN}`\n const employeeEmail = employeeOverride ?? `employee@${DEFAULT_DERIVED_EMAIL_DOMAIN}`\n const adminPassword = readEnvValue('OM_INIT_ADMIN_PASSWORD') || 'secret'\n const employeePassword = readEnvValue('OM_INIT_EMPLOYEE_PASSWORD') || 'secret'\n const adminPasswordHash = adminPassword ? await resolvePasswordHash({ email: adminEmail, password: adminPassword }) : null\n const employeePasswordHash = employeePassword\n ? await resolvePasswordHash({ email: employeeEmail, password: employeePassword })\n : null\n addUniqueBaseUser(baseUsers, { email: adminEmail, roles: ['admin'], passwordHash: adminPasswordHash })\n addUniqueBaseUser(baseUsers, { email: employeeEmail, roles: ['employee'], passwordHash: employeePasswordHash })\n }\n const passwordHash = await resolvePasswordHash(primaryUser)\n\n await em.transactional(async (tem) => {\n const tenant = tem.create(Tenant, {\n name: `${options.orgName} Tenant`,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n tem.persist(tenant)\n await tem.flush()\n\n const organization = tem.create(Organization, {\n name: options.orgName,\n tenant,\n isActive: true,\n depth: 0,\n ancestorIds: [],\n childIds: [],\n descendantIds: [],\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n tem.persist(organization)\n await tem.flush()\n\n tenantId = String(tenant.id)\n organizationId = String(organization.id)\n const roleTenantId = tenantId\n\n if (isTenantDataEncryptionEnabled()) {\n try {\n const kms = createKmsService()\n if (kms.isHealthy()) {\n if (isEncryptionDebugEnabled()) {\n console.info('\uD83D\uDD11 [encryption][setup] provisioning tenant DEK', { tenantId: String(tenant.id) })\n }\n await kms.createTenantDek(String(tenant.id))\n if (isEncryptionDebugEnabled()) {\n console.info('\uD83D\uDD11 [encryption][setup] created tenant DEK during setup', { tenantId: String(tenant.id) })\n }\n } else {\n if (isEncryptionDebugEnabled()) {\n console.warn('\u26A0\uFE0F [encryption][setup] KMS not healthy, skipping tenant DEK creation', { tenantId: String(tenant.id) })\n }\n }\n } catch (err) {\n if (isEncryptionDebugEnabled()) {\n console.warn('\u26A0\uFE0F [encryption][setup] Failed to create tenant DEK', err)\n }\n }\n }\n\n await ensureRolesInContext(tem, roleNames, roleTenantId)\n await tem.flush()\n\n if (isTenantDataEncryptionEnabled()) {\n for (const spec of DEFAULT_ENCRYPTION_MAPS) {\n const existing = await tem.findOne(EncryptionMap, { entityId: spec.entityId, tenantId: tenant.id, organizationId: organization.id, deletedAt: null })\n if (!existing) {\n tem.persist(tem.create(EncryptionMap, {\n entityId: spec.entityId,\n tenantId: tenant.id,\n organizationId: organization.id,\n fieldsJson: spec.fields,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n }))\n } else {\n existing.fieldsJson = spec.fields\n existing.isActive = true\n }\n }\n await tem.flush()\n }\n })\n\n await em.transactional(async (tem) => {\n if (!tenantId || !organizationId) return\n const roleTenantId = tenantId\n const encryptionService = isTenantDataEncryptionEnabled()\n ? new TenantDataEncryptionService(tem as any, { kms: createKmsService() })\n : null\n if (encryptionService) {\n await encryptionService.invalidateMap('auth:user', String(tenantId), String(organizationId))\n await encryptionService.invalidateMap('auth:user', String(tenantId), null)\n }\n\n for (const base of baseUsers) {\n const resolvedPasswordHash = base.passwordHash ?? passwordHash\n let user = await tem.findOne(User, { email: base.email })\n const confirm = primaryUser.confirm ?? true\n const encryptedPayload = encryptionService\n ? await encryptionService.encryptEntityPayload('auth:user', { email: base.email }, tenantId, organizationId)\n : { email: base.email, emailHash: computeEmailHash(base.email) }\n if (user) {\n user.passwordHash = resolvedPasswordHash\n user.organizationId = organizationId\n user.tenantId = tenantId\n if (isTenantDataEncryptionEnabled()) {\n user.email = encryptedPayload.email as any\n user.emailHash = (encryptedPayload as any).emailHash ?? computeEmailHash(base.email)\n }\n if (base.name) user.name = base.name\n if (confirm) user.isConfirmed = true\n tem.persist(user)\n userSnapshots.push({ user, roles: base.roles, created: false })\n } else {\n user = tem.create(User, {\n email: (encryptedPayload as any).email ?? base.email,\n emailHash: isTenantDataEncryptionEnabled() ? (encryptedPayload as any).emailHash ?? computeEmailHash(base.email) : undefined,\n passwordHash: resolvedPasswordHash,\n organizationId,\n tenantId,\n name: base.name ?? undefined,\n isConfirmed: confirm,\n createdAt: new Date(),\n })\n tem.persist(user)\n userSnapshots.push({ user, roles: base.roles, created: true })\n }\n await tem.flush()\n for (const roleName of base.roles) {\n const role = await findRoleByNameOrFail(tem, roleName, roleTenantId)\n const existingLink = await tem.findOne(UserRole, { user, role })\n if (!existingLink) tem.persist(tem.create(UserRole, { user, role, createdAt: new Date() }))\n }\n await tem.flush()\n }\n })\n }\n\n if (!tenantId || !organizationId) {\n throw new Error('SETUP_FAILED')\n }\n\n if (!reusedExistingUser) {\n await rebuildHierarchyForTenant(em, tenantId)\n }\n\n const resolvedModules = options.modules ?? tryGetModules()\n await ensureDefaultRoleAcls(em, tenantId, resolvedModules, { includeSuperadminRole })\n await deactivateDemoSuperAdminIfSelfOnboardingEnabled(em)\n\n // Call module onTenantCreated hooks\n for (const mod of resolvedModules) {\n if (mod.setup?.onTenantCreated) {\n await mod.setup.onTenantCreated({ em, tenantId, organizationId })\n }\n }\n\n return {\n tenantId,\n organizationId,\n users: userSnapshots,\n reusedExistingUser,\n }\n}\n\nfunction resolvePrimaryName(input: PrimaryUserInput): string | null {\n if (input.displayName && input.displayName.trim()) return input.displayName.trim()\n const parts = [input.firstName, input.lastName].map((value) => value?.trim()).filter(Boolean)\n if (parts.length) return parts.join(' ')\n return null\n}\n\nfunction readEnvValue(key: string): string | undefined {\n const value = process.env[key]\n if (typeof value !== 'string') return undefined\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : undefined\n}\n\nfunction addUniqueBaseUser(\n baseUsers: Array<{ email: string; roles: string[]; name?: string | null; passwordHash?: string | null }>,\n entry: { email: string; roles: string[]; name?: string | null; passwordHash?: string | null },\n) {\n if (!entry.email) return\n const normalized = entry.email.toLowerCase()\n if (baseUsers.some((user) => user.email.toLowerCase() === normalized)) return\n baseUsers.push(entry)\n}\n\nfunction isDemoModeEnabled(): boolean {\n const parsed = parseBooleanToken(process.env.DEMO_MODE ?? '')\n return parsed === false ? false : true\n}\n\nfunction shouldKeepDemoSuperadminDuringInit(): boolean {\n if (process.env.OM_INIT_FLOW !== 'true') return false\n if (!readEnvValue('OM_INIT_SUPERADMIN_EMAIL')) return false\n return isDemoModeEnabled()\n}\n\nasync function resolvePasswordHash(input: PrimaryUserInput): Promise<string | null> {\n if (typeof input.hashedPassword === 'string') return input.hashedPassword\n if (input.password) return hash(input.password, 10)\n return null\n}\n\nasync function ensureDefaultRoleAcls(\n em: EntityManager,\n tenantId: string,\n modules: Module[],\n options: { includeSuperadminRole?: boolean } = {},\n) {\n const includeSuperadminRole = options.includeSuperadminRole ?? true\n const roleTenantId = normalizeTenantId(tenantId) ?? null\n const superadminRole = includeSuperadminRole ? await findRoleByName(em, 'superadmin', roleTenantId) : null\n const adminRole = await findRoleByName(em, 'admin', roleTenantId)\n const employeeRole = await findRoleByName(em, 'employee', roleTenantId)\n\n // Merge features from all enabled modules' setup configs\n const builtInRoles = ['superadmin', 'admin', 'employee'] as const\n const superadminFeatures: string[] = []\n const adminFeatures: string[] = []\n const employeeFeatures: string[] = []\n const customRoleFeatures = new Map<string, string[]>()\n\n for (const mod of modules) {\n const roleFeatures = mod.setup?.defaultRoleFeatures\n if (!roleFeatures) continue\n if (roleFeatures.superadmin) superadminFeatures.push(...roleFeatures.superadmin)\n if (roleFeatures.admin) adminFeatures.push(...roleFeatures.admin)\n if (roleFeatures.employee) employeeFeatures.push(...roleFeatures.employee)\n\n // Collect features for custom roles (any key not in builtInRoles)\n for (const [roleName, features] of Object.entries(roleFeatures)) {\n if ((builtInRoles as readonly string[]).includes(roleName)) continue\n if (!Array.isArray(features)) continue\n const existing = customRoleFeatures.get(roleName) ?? []\n existing.push(...features)\n customRoleFeatures.set(roleName, existing)\n }\n }\n\n console.log('\u2705 Seeded default role features', {\n superadmin: superadminFeatures,\n admin: adminFeatures,\n employee: employeeFeatures,\n ...(customRoleFeatures.size > 0\n ? Object.fromEntries(customRoleFeatures)\n : {}),\n })\n\n if (includeSuperadminRole && superadminRole) {\n await ensureRoleAclFor(em, superadminRole, tenantId, superadminFeatures, { isSuperAdmin: true })\n }\n if (adminRole) {\n await ensureRoleAclFor(em, adminRole, tenantId, adminFeatures)\n }\n if (employeeRole) {\n await ensureRoleAclFor(em, employeeRole, tenantId, employeeFeatures)\n }\n\n // Seed ACLs for custom roles defined by app modules\n for (const [roleName, features] of customRoleFeatures) {\n const role = await findRoleByName(em, roleName, roleTenantId)\n if (role) {\n await ensureRoleAclFor(em, role, tenantId, features)\n }\n }\n}\n\nasync function ensureRoleAclFor(\n em: EntityManager,\n role: Role,\n tenantId: string,\n features: string[],\n options: { isSuperAdmin?: boolean } = {},\n) {\n const existing = await em.findOne(RoleAcl, { role, tenantId })\n if (!existing) {\n const acl = em.create(RoleAcl, {\n role,\n tenantId,\n featuresJson: features,\n isSuperAdmin: !!options.isSuperAdmin,\n createdAt: new Date(),\n })\n await em.persistAndFlush(acl)\n return\n }\n const currentFeatures = Array.isArray(existing.featuresJson) ? existing.featuresJson : []\n const merged = Array.from(new Set([...currentFeatures, ...features]))\n const changed =\n merged.length !== currentFeatures.length ||\n merged.some((value, index) => value !== currentFeatures[index])\n if (changed) existing.featuresJson = merged\n if (options.isSuperAdmin && !existing.isSuperAdmin) {\n existing.isSuperAdmin = true\n }\n if (changed || options.isSuperAdmin) {\n await em.persistAndFlush(existing)\n }\n}\n\nasync function deactivateDemoSuperAdminIfSelfOnboardingEnabled(em: EntityManager) {\n if (process.env.SELF_SERVICE_ONBOARDING_ENABLED !== 'true') return\n if (shouldKeepDemoSuperadminDuringInit()) return\n try {\n const user = await em.findOne(User, { email: DEMO_SUPERADMIN_EMAIL })\n if (!user) return\n let dirty = false\n if (user.passwordHash) {\n user.passwordHash = null\n dirty = true\n }\n if (user.isConfirmed !== false) {\n user.isConfirmed = false\n dirty = true\n }\n if (dirty) {\n await em.persistAndFlush(user)\n }\n } catch (error) {\n console.error('[auth.setup] failed to deactivate demo superadmin user', error)\n }\n}\n\n/** Try to get modules from runtime registry; returns empty array if not yet registered. */\nfunction tryGetModules(): Module[] {\n try {\n const { getModules } = require('@open-mercato/shared/lib/modules/registry')\n return getModules()\n } catch {\n return []\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,2 @@
1
+ export * from "../../helpers/integration/api.js";
2
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/testing/integration/api.ts"],
4
+ "sourcesContent": ["export * from '../../helpers/integration/api'\n"],
5
+ "mappings": "AAAA,cAAc;",
6
+ "names": []
7
+ }
@@ -0,0 +1,2 @@
1
+ export * from "../../helpers/integration/auth.js";
2
+ //# sourceMappingURL=auth.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/testing/integration/auth.ts"],
4
+ "sourcesContent": ["export * from '../../helpers/integration/auth'\n"],
5
+ "mappings": "AAAA,cAAc;",
6
+ "names": []
7
+ }
@@ -0,0 +1,2 @@
1
+ export * from "../../helpers/integration/authFixtures.js";
2
+ //# sourceMappingURL=authFixtures.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/testing/integration/authFixtures.ts"],
4
+ "sourcesContent": ["export * from '../../helpers/integration/authFixtures'\n"],
5
+ "mappings": "AAAA,cAAc;",
6
+ "names": []
7
+ }
@@ -0,0 +1,2 @@
1
+ export * from "../../helpers/integration/authUi.js";
2
+ //# sourceMappingURL=authUi.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/testing/integration/authUi.ts"],
4
+ "sourcesContent": ["export * from '../../helpers/integration/authUi'\n"],
5
+ "mappings": "AAAA,cAAc;",
6
+ "names": []
7
+ }
@@ -0,0 +1,2 @@
1
+ export * from "../../helpers/integration/crmFixtures.js";
2
+ //# sourceMappingURL=crmFixtures.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/testing/integration/crmFixtures.ts"],
4
+ "sourcesContent": ["export * from '../../helpers/integration/crmFixtures'\n"],
5
+ "mappings": "AAAA,cAAc;",
6
+ "names": []
7
+ }
@@ -0,0 +1,2 @@
1
+ export * from "../../helpers/integration/dictionariesFixtures.js";
2
+ //# sourceMappingURL=dictionariesFixtures.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/testing/integration/dictionariesFixtures.ts"],
4
+ "sourcesContent": ["export * from '../../helpers/integration/dictionariesFixtures'\n"],
5
+ "mappings": "AAAA,cAAc;",
6
+ "names": []
7
+ }
@@ -0,0 +1,2 @@
1
+ export * from "../../helpers/integration/generalFixtures.js";
2
+ //# sourceMappingURL=generalFixtures.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/testing/integration/generalFixtures.ts"],
4
+ "sourcesContent": ["export * from '../../helpers/integration/generalFixtures'\n"],
5
+ "mappings": "AAAA,cAAc;",
6
+ "names": []
7
+ }
@@ -0,0 +1,48 @@
1
+ import { getAuthToken, apiRequest, postForm } from "../../helpers/integration/api.js";
2
+ import { DEFAULT_CREDENTIALS } from "../../helpers/integration/auth.js";
3
+ import { createUserViaUi } from "../../helpers/integration/authUi.js";
4
+ import {
5
+ createCompanyFixture,
6
+ createPersonFixture,
7
+ createDealFixture,
8
+ createPipelineFixture,
9
+ createPipelineStageFixture,
10
+ deleteEntityByBody,
11
+ deleteEntityIfExists
12
+ } from "../../helpers/integration/crmFixtures.js";
13
+ import {
14
+ readJsonSafe,
15
+ getTokenContext,
16
+ getTokenScope,
17
+ expectId,
18
+ deleteEntityByPathIfExists,
19
+ deleteGeneralEntityIfExists
20
+ } from "../../helpers/integration/generalFixtures.js";
21
+ import { createDictionaryFixture } from "../../helpers/integration/dictionariesFixtures.js";
22
+ import { createRoleFixture, deleteRoleIfExists, createUserFixture, deleteUserIfExists } from "../../helpers/integration/authFixtures.js";
23
+ export {
24
+ DEFAULT_CREDENTIALS,
25
+ apiRequest,
26
+ createCompanyFixture,
27
+ createDealFixture,
28
+ createDictionaryFixture,
29
+ createPersonFixture,
30
+ createPipelineFixture,
31
+ createPipelineStageFixture,
32
+ createRoleFixture,
33
+ createUserFixture,
34
+ createUserViaUi,
35
+ deleteEntityByBody,
36
+ deleteEntityByPathIfExists,
37
+ deleteEntityIfExists,
38
+ deleteGeneralEntityIfExists,
39
+ deleteRoleIfExists,
40
+ deleteUserIfExists,
41
+ expectId,
42
+ getAuthToken,
43
+ getTokenContext,
44
+ getTokenScope,
45
+ postForm,
46
+ readJsonSafe
47
+ };
48
+ //# sourceMappingURL=index.js.map