@open-mercato/core 0.6.2-develop.3461.1.605f31c2c9 → 0.6.2

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 (173) hide show
  1. package/.turbo/turbo-build.log +1 -1
  2. package/dist/helpers/integration/queue-runner.js +15 -3
  3. package/dist/helpers/integration/queue-runner.js.map +2 -2
  4. package/dist/helpers/integration/queue.js +1 -1
  5. package/dist/helpers/integration/queue.js.map +2 -2
  6. package/dist/helpers/integration/salesUi.js +24 -1
  7. package/dist/helpers/integration/salesUi.js.map +2 -2
  8. package/dist/modules/auth/api/roles/acl/route.js +37 -1
  9. package/dist/modules/auth/api/roles/acl/route.js.map +2 -2
  10. package/dist/modules/auth/api/roles/route.js +36 -2
  11. package/dist/modules/auth/api/roles/route.js.map +2 -2
  12. package/dist/modules/auth/api/users/acl/route.js +36 -1
  13. package/dist/modules/auth/api/users/acl/route.js.map +2 -2
  14. package/dist/modules/auth/api/users/route.js +101 -13
  15. package/dist/modules/auth/api/users/route.js.map +2 -2
  16. package/dist/modules/auth/backend/roles/[id]/edit/page.js +32 -14
  17. package/dist/modules/auth/backend/roles/[id]/edit/page.js.map +2 -2
  18. package/dist/modules/auth/backend/users/[id]/edit/page.js +1 -1
  19. package/dist/modules/auth/backend/users/[id]/edit/page.js.map +2 -2
  20. package/dist/modules/auth/backend/users/create/page.js +1 -1
  21. package/dist/modules/auth/backend/users/create/page.js.map +2 -2
  22. package/dist/modules/auth/backend/users/roleOptions.js +1 -1
  23. package/dist/modules/auth/backend/users/roleOptions.js.map +2 -2
  24. package/dist/modules/auth/commands/roles.js +8 -0
  25. package/dist/modules/auth/commands/roles.js.map +2 -2
  26. package/dist/modules/auth/commands/users.js +3 -0
  27. package/dist/modules/auth/commands/users.js.map +2 -2
  28. package/dist/modules/auth/components/AclEditor.js +53 -26
  29. package/dist/modules/auth/components/AclEditor.js.map +2 -2
  30. package/dist/modules/auth/frontend/login.js +35 -0
  31. package/dist/modules/auth/frontend/login.js.map +2 -2
  32. package/dist/modules/auth/lib/grantChecks.js +97 -2
  33. package/dist/modules/auth/lib/grantChecks.js.map +2 -2
  34. package/dist/modules/business_rules/lib/expression-evaluator.js +9 -7
  35. package/dist/modules/business_rules/lib/expression-evaluator.js.map +2 -2
  36. package/dist/modules/business_rules/lib/rule-evaluator.js +3 -3
  37. package/dist/modules/business_rules/lib/rule-evaluator.js.map +2 -2
  38. package/dist/modules/customers/ai-agents.js +10 -1
  39. package/dist/modules/customers/ai-agents.js.map +2 -2
  40. package/dist/modules/customers/ai-tools/settings-pack.js +55 -1
  41. package/dist/modules/customers/ai-tools/settings-pack.js.map +2 -2
  42. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js +13 -5
  43. package/dist/modules/customers/components/detail/schedule/useScheduleFormState.js.map +2 -2
  44. package/dist/modules/customers/lib/personCompanyLinkTable.js +4 -30
  45. package/dist/modules/customers/lib/personCompanyLinkTable.js.map +2 -2
  46. package/dist/modules/customers/migrations/Migration20260521175027.js +12 -0
  47. package/dist/modules/customers/migrations/Migration20260521175027.js.map +7 -0
  48. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js +41 -12
  49. package/dist/modules/dashboards/components/WidgetVisibilityEditor.js.map +2 -2
  50. package/dist/modules/data_sync/api/options.js +2 -0
  51. package/dist/modules/data_sync/api/options.js.map +2 -2
  52. package/dist/modules/data_sync/api/run.js +77 -58
  53. package/dist/modules/data_sync/api/run.js.map +2 -2
  54. package/dist/modules/data_sync/backend/data-sync/page.js +3 -2
  55. package/dist/modules/data_sync/backend/data-sync/page.js.map +2 -2
  56. package/dist/modules/data_sync/components/IntegrationScheduleTab.js +8 -3
  57. package/dist/modules/data_sync/components/IntegrationScheduleTab.js.map +2 -2
  58. package/dist/modules/integrations/backend/integrations/[id]/page.js +15 -13
  59. package/dist/modules/integrations/backend/integrations/[id]/page.js.map +2 -2
  60. package/dist/modules/integrations/data/validators.js +9 -6
  61. package/dist/modules/integrations/data/validators.js.map +2 -2
  62. package/dist/modules/messages/api/route.js +2 -2
  63. package/dist/modules/messages/api/route.js.map +2 -2
  64. package/dist/modules/messages/commands/messages.js +42 -2
  65. package/dist/modules/messages/commands/messages.js.map +2 -2
  66. package/dist/modules/messages/components/MessagesInboxPageClient.js +70 -89
  67. package/dist/modules/messages/components/MessagesInboxPageClient.js.map +2 -2
  68. package/dist/modules/messages/components/defaults/DefaultMessageListItem.js +8 -6
  69. package/dist/modules/messages/components/defaults/DefaultMessageListItem.js.map +2 -2
  70. package/dist/modules/messages/components/inboxFilters.js +133 -0
  71. package/dist/modules/messages/components/inboxFilters.js.map +7 -0
  72. package/dist/modules/messages/components/messageListLabels.js +14 -0
  73. package/dist/modules/messages/components/messageListLabels.js.map +7 -0
  74. package/dist/modules/messages/components/useMessagesInboxBulkActions.js +47 -23
  75. package/dist/modules/messages/components/useMessagesInboxBulkActions.js.map +2 -2
  76. package/dist/modules/messages/data/validators.js +8 -6
  77. package/dist/modules/messages/data/validators.js.map +2 -2
  78. package/dist/modules/progress/api/jobs/route.js +26 -16
  79. package/dist/modules/progress/api/jobs/route.js.map +2 -2
  80. package/dist/modules/query_index/di.js +8 -6
  81. package/dist/modules/query_index/di.js.map +2 -2
  82. package/dist/modules/query_index/lib/indexer.js +12 -10
  83. package/dist/modules/query_index/lib/indexer.js.map +2 -2
  84. package/dist/modules/query_index/subscribers/upsert_one.js +7 -1
  85. package/dist/modules/query_index/subscribers/upsert_one.js.map +2 -2
  86. package/dist/modules/sales/api/order-adjustments/route.js.map +2 -2
  87. package/dist/modules/sales/api/quote-adjustments/route.js.map +2 -2
  88. package/dist/modules/sales/commands/documents.js +104 -0
  89. package/dist/modules/sales/commands/documents.js.map +2 -2
  90. package/dist/modules/sales/data/validators.js +20 -1
  91. package/dist/modules/sales/data/validators.js.map +2 -2
  92. package/dist/modules/sales/lib/makeSalesLineRoute.js.map +2 -2
  93. package/dist/modules/sync_excel/api/import/route.js +126 -116
  94. package/dist/modules/sync_excel/api/import/route.js.map +2 -2
  95. package/dist/modules/sync_excel/lib/adapters/customers.js +1 -0
  96. package/dist/modules/sync_excel/lib/adapters/customers.js.map +2 -2
  97. package/dist/modules/translations/components/TranslationManager.js +9 -4
  98. package/dist/modules/translations/components/TranslationManager.js.map +2 -2
  99. package/dist/modules/workflows/lib/activity-executor.js.map +2 -2
  100. package/dist/modules/workflows/lib/event-trigger-service.js +23 -11
  101. package/dist/modules/workflows/lib/event-trigger-service.js.map +2 -2
  102. package/jest.config.cjs +4 -1
  103. package/package.json +15 -16
  104. package/src/helpers/integration/queue-runner.ts +21 -2
  105. package/src/helpers/integration/queue.ts +1 -1
  106. package/src/helpers/integration/salesUi.ts +26 -1
  107. package/src/modules/auth/api/roles/acl/route.ts +39 -1
  108. package/src/modules/auth/api/roles/route.ts +38 -2
  109. package/src/modules/auth/api/users/acl/route.ts +41 -1
  110. package/src/modules/auth/api/users/route.ts +105 -12
  111. package/src/modules/auth/backend/roles/[id]/edit/page.tsx +35 -13
  112. package/src/modules/auth/backend/users/[id]/edit/page.tsx +1 -1
  113. package/src/modules/auth/backend/users/create/page.tsx +1 -1
  114. package/src/modules/auth/backend/users/roleOptions.ts +2 -1
  115. package/src/modules/auth/commands/roles.ts +8 -0
  116. package/src/modules/auth/commands/users.ts +3 -0
  117. package/src/modules/auth/components/AclEditor.tsx +50 -24
  118. package/src/modules/auth/frontend/login.tsx +40 -0
  119. package/src/modules/auth/lib/grantChecks.ts +116 -2
  120. package/src/modules/business_rules/lib/expression-evaluator.ts +9 -13
  121. package/src/modules/business_rules/lib/rule-evaluator.ts +3 -3
  122. package/src/modules/customers/ai-agents.ts +10 -1
  123. package/src/modules/customers/ai-tools/settings-pack.ts +62 -1
  124. package/src/modules/customers/components/detail/schedule/useScheduleFormState.ts +18 -7
  125. package/src/modules/customers/lib/personCompanyLinkTable.ts +33 -41
  126. package/src/modules/customers/migrations/Migration20260521175027.ts +39 -0
  127. package/src/modules/dashboards/components/WidgetVisibilityEditor.tsx +38 -12
  128. package/src/modules/data_sync/api/options.ts +2 -0
  129. package/src/modules/data_sync/api/run.ts +80 -61
  130. package/src/modules/data_sync/backend/data-sync/page.tsx +10 -0
  131. package/src/modules/data_sync/components/IntegrationScheduleTab.tsx +17 -3
  132. package/src/modules/data_sync/i18n/de.json +3 -0
  133. package/src/modules/data_sync/i18n/en.json +3 -0
  134. package/src/modules/data_sync/i18n/es.json +3 -0
  135. package/src/modules/data_sync/i18n/pl.json +3 -0
  136. package/src/modules/data_sync/lib/adapter.ts +9 -0
  137. package/src/modules/integrations/backend/integrations/[id]/page.tsx +15 -13
  138. package/src/modules/integrations/data/validators.ts +5 -4
  139. package/src/modules/messages/api/route.ts +2 -2
  140. package/src/modules/messages/commands/messages.ts +54 -2
  141. package/src/modules/messages/components/MessagesInboxPageClient.tsx +80 -92
  142. package/src/modules/messages/components/defaults/DefaultMessageListItem.tsx +9 -5
  143. package/src/modules/messages/components/inboxFilters.ts +162 -0
  144. package/src/modules/messages/components/messageListLabels.ts +29 -0
  145. package/src/modules/messages/components/useMessagesInboxBulkActions.ts +58 -26
  146. package/src/modules/messages/data/validators.ts +7 -5
  147. package/src/modules/messages/i18n/de.json +7 -4
  148. package/src/modules/messages/i18n/en.json +7 -4
  149. package/src/modules/messages/i18n/es.json +7 -4
  150. package/src/modules/messages/i18n/pl.json +7 -4
  151. package/src/modules/progress/api/jobs/route.ts +30 -20
  152. package/src/modules/query_index/di.ts +9 -7
  153. package/src/modules/query_index/lib/indexer.ts +13 -11
  154. package/src/modules/query_index/subscribers/upsert_one.ts +9 -1
  155. package/src/modules/sales/api/order-adjustments/route.ts +2 -1
  156. package/src/modules/sales/api/quote-adjustments/route.ts +2 -1
  157. package/src/modules/sales/commands/documents.ts +116 -0
  158. package/src/modules/sales/data/validators.ts +38 -0
  159. package/src/modules/sales/i18n/de.json +2 -0
  160. package/src/modules/sales/i18n/en.json +2 -0
  161. package/src/modules/sales/i18n/es.json +2 -0
  162. package/src/modules/sales/i18n/pl.json +2 -0
  163. package/src/modules/sales/lib/makeSalesLineRoute.ts +2 -1
  164. package/src/modules/staff/i18n/de.json +1 -0
  165. package/src/modules/staff/i18n/en.json +1 -0
  166. package/src/modules/staff/i18n/es.json +1 -0
  167. package/src/modules/staff/i18n/pl.json +1 -0
  168. package/src/modules/sync_excel/api/import/route.ts +141 -131
  169. package/src/modules/sync_excel/lib/adapters/customers.ts +1 -0
  170. package/src/modules/translations/components/TranslationManager.tsx +9 -4
  171. package/src/modules/workflows/lib/activity-executor.ts +4 -3
  172. package/src/modules/workflows/lib/event-trigger-service.ts +24 -11
  173. package/tsconfig.json +1 -0
@@ -1,4 +1,4 @@
1
- [build:core] found 2549 entry points
1
+ [build:core] found 2554 entry points
2
2
  [build:core] built successfully
3
3
  [build:core:generated] found 172 entry points
4
4
  [build:core:generated] built successfully
@@ -3,13 +3,24 @@ import { fileURLToPath } from "node:url";
3
3
  import { bootstrapFromAppRoot } from "@open-mercato/shared/lib/bootstrap/dynamicLoader";
4
4
  import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
5
5
  import { createQueue } from "@open-mercato/queue";
6
+ const bootstrapCache = /* @__PURE__ */ new Map();
7
+ function getBootstrapData(appRoot) {
8
+ const resolvedAppRoot = path.resolve(appRoot);
9
+ const cached = bootstrapCache.get(resolvedAppRoot);
10
+ if (cached) return cached;
11
+ const promise = bootstrapFromAppRoot(resolvedAppRoot);
12
+ bootstrapCache.set(resolvedAppRoot, promise);
13
+ return promise;
14
+ }
6
15
  async function drainQueueFromAppRoot(queueName, options) {
7
- const data = await bootstrapFromAppRoot(options.appRoot);
16
+ const data = await getBootstrapData(options.appRoot);
8
17
  const worker = data.modules.flatMap((module) => module.workers ?? []).find((entry) => entry.queue === queueName);
9
18
  if (!worker) return 0;
10
19
  const container = await createRequestContainer();
11
20
  const queue = createQueue(queueName, "local", {
12
- baseDir: path.resolve(options.appRoot, ".mercato/queue"),
21
+ baseDir: path.resolve(
22
+ options.queueBaseDir?.trim() || process.env.QUEUE_BASE_DIR?.trim() || path.resolve(options.appRoot, ".mercato/queue")
23
+ ),
13
24
  concurrency: 1
14
25
  });
15
26
  const resolve = (name) => container.resolve(name);
@@ -37,7 +48,8 @@ async function runQueueDrainFromEnv() {
37
48
  if (!queueName || !appRoot) throw new Error("Missing queue drain environment");
38
49
  const processed = await drainQueueFromAppRoot(queueName, {
39
50
  appRoot: path.resolve(appRoot),
40
- jobLimit
51
+ jobLimit,
52
+ queueBaseDir: process.env.QUEUE_BASE_DIR
41
53
  });
42
54
  console.log(JSON.stringify({ processed }));
43
55
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/helpers/integration/queue-runner.ts"],
4
- "sourcesContent": ["import path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { bootstrapFromAppRoot } from '@open-mercato/shared/lib/bootstrap/dynamicLoader'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { createQueue } from '@open-mercato/queue'\n\nexport type QueueDrainRunnerOptions = {\n appRoot: string\n jobLimit: number\n}\n\nexport async function drainQueueFromAppRoot(\n queueName: string,\n options: QueueDrainRunnerOptions,\n): Promise<number> {\n const data = await bootstrapFromAppRoot(options.appRoot)\n const worker = data.modules\n .flatMap((module) => module.workers ?? [])\n .find((entry) => entry.queue === queueName)\n if (!worker) return 0\n\n const container = await createRequestContainer()\n const queue = createQueue(queueName, 'local', {\n baseDir: path.resolve(options.appRoot, '.mercato/queue'),\n concurrency: 1,\n })\n const resolve = <T = unknown>(name: string): T => container.resolve(name) as T\n\n try {\n let processedJobs = 0\n while (true) {\n const result = await queue.process(\n async (job, ctx) => {\n await Promise.resolve(worker.handler(job, { ...ctx, resolve }))\n },\n { limit: options.jobLimit },\n )\n const handled = result.processed + result.failed\n processedJobs += handled\n if (handled === 0) return processedJobs\n }\n } finally {\n await queue.close()\n }\n}\n\nexport async function runQueueDrainFromEnv(): Promise<void> {\n const queueName = process.env.OM_INTEGRATION_QUEUE_NAME?.trim()\n const appRoot = process.env.OM_INTEGRATION_APP_ROOT?.trim()\n const jobLimit = Number.parseInt(process.env.OM_INTEGRATION_QUEUE_JOB_LIMIT || '100', 10) || 100\n if (!queueName || !appRoot) throw new Error('Missing queue drain environment')\n\n const processed = await drainQueueFromAppRoot(queueName, {\n appRoot: path.resolve(appRoot),\n jobLimit,\n })\n console.log(JSON.stringify({ processed }))\n}\n\nconst currentFile = fileURLToPath(import.meta.url)\nconst invokedFile = process.argv[1] ? path.resolve(process.argv[1]) : null\n\nif (invokedFile === currentFile) {\n runQueueDrainFromEnv()\n .then(() => {\n process.exit(0)\n })\n .catch((error) => {\n console.error(error)\n process.exit(1)\n })\n}\n"],
5
- "mappings": "AAAA,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAC9B,SAAS,4BAA4B;AACrC,SAAS,8BAA8B;AACvC,SAAS,mBAAmB;AAO5B,eAAsB,sBACpB,WACA,SACiB;AACjB,QAAM,OAAO,MAAM,qBAAqB,QAAQ,OAAO;AACvD,QAAM,SAAS,KAAK,QACjB,QAAQ,CAAC,WAAW,OAAO,WAAW,CAAC,CAAC,EACxC,KAAK,CAAC,UAAU,MAAM,UAAU,SAAS;AAC5C,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,QAAQ,YAAY,WAAW,SAAS;AAAA,IAC5C,SAAS,KAAK,QAAQ,QAAQ,SAAS,gBAAgB;AAAA,IACvD,aAAa;AAAA,EACf,CAAC;AACD,QAAM,UAAU,CAAc,SAAoB,UAAU,QAAQ,IAAI;AAExE,MAAI;AACF,QAAI,gBAAgB;AACpB,WAAO,MAAM;AACX,YAAM,SAAS,MAAM,MAAM;AAAA,QACzB,OAAO,KAAK,QAAQ;AAClB,gBAAM,QAAQ,QAAQ,OAAO,QAAQ,KAAK,EAAE,GAAG,KAAK,QAAQ,CAAC,CAAC;AAAA,QAChE;AAAA,QACA,EAAE,OAAO,QAAQ,SAAS;AAAA,MAC5B;AACA,YAAM,UAAU,OAAO,YAAY,OAAO;AAC1C,uBAAiB;AACjB,UAAI,YAAY,EAAG,QAAO;AAAA,IAC5B;AAAA,EACF,UAAE;AACA,UAAM,MAAM,MAAM;AAAA,EACpB;AACF;AAEA,eAAsB,uBAAsC;AAC1D,QAAM,YAAY,QAAQ,IAAI,2BAA2B,KAAK;AAC9D,QAAM,UAAU,QAAQ,IAAI,yBAAyB,KAAK;AAC1D,QAAM,WAAW,OAAO,SAAS,QAAQ,IAAI,kCAAkC,OAAO,EAAE,KAAK;AAC7F,MAAI,CAAC,aAAa,CAAC,QAAS,OAAM,IAAI,MAAM,iCAAiC;AAE7E,QAAM,YAAY,MAAM,sBAAsB,WAAW;AAAA,IACvD,SAAS,KAAK,QAAQ,OAAO;AAAA,IAC7B;AAAA,EACF,CAAC;AACD,UAAQ,IAAI,KAAK,UAAU,EAAE,UAAU,CAAC,CAAC;AAC3C;AAEA,MAAM,cAAc,cAAc,YAAY,GAAG;AACjD,MAAM,cAAc,QAAQ,KAAK,CAAC,IAAI,KAAK,QAAQ,QAAQ,KAAK,CAAC,CAAC,IAAI;AAEtE,IAAI,gBAAgB,aAAa;AAC/B,uBAAqB,EAClB,KAAK,MAAM;AACV,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,YAAQ,MAAM,KAAK;AACnB,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACL;",
4
+ "sourcesContent": ["import path from 'node:path'\nimport { fileURLToPath } from 'node:url'\nimport { bootstrapFromAppRoot } from '@open-mercato/shared/lib/bootstrap/dynamicLoader'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { createQueue } from '@open-mercato/queue'\n\nexport type QueueDrainRunnerOptions = {\n appRoot: string\n jobLimit: number\n queueBaseDir?: string\n}\n\ntype BootstrapData = Awaited<ReturnType<typeof bootstrapFromAppRoot>>\n\nconst bootstrapCache = new Map<string, Promise<BootstrapData>>()\n\nfunction getBootstrapData(appRoot: string): Promise<BootstrapData> {\n const resolvedAppRoot = path.resolve(appRoot)\n const cached = bootstrapCache.get(resolvedAppRoot)\n if (cached) return cached\n const promise = bootstrapFromAppRoot(resolvedAppRoot)\n bootstrapCache.set(resolvedAppRoot, promise)\n return promise\n}\n\nexport async function drainQueueFromAppRoot(\n queueName: string,\n options: QueueDrainRunnerOptions,\n): Promise<number> {\n const data = await getBootstrapData(options.appRoot)\n const worker = data.modules\n .flatMap((module) => module.workers ?? [])\n .find((entry) => entry.queue === queueName)\n if (!worker) return 0\n\n const container = await createRequestContainer()\n const queue = createQueue(queueName, 'local', {\n baseDir: path.resolve(\n options.queueBaseDir?.trim()\n || process.env.QUEUE_BASE_DIR?.trim()\n || path.resolve(options.appRoot, '.mercato/queue'),\n ),\n concurrency: 1,\n })\n const resolve = <T = unknown>(name: string): T => container.resolve(name) as T\n\n try {\n let processedJobs = 0\n while (true) {\n const result = await queue.process(\n async (job, ctx) => {\n await Promise.resolve(worker.handler(job, { ...ctx, resolve }))\n },\n { limit: options.jobLimit },\n )\n const handled = result.processed + result.failed\n processedJobs += handled\n if (handled === 0) return processedJobs\n }\n } finally {\n await queue.close()\n }\n}\n\nexport async function runQueueDrainFromEnv(): Promise<void> {\n const queueName = process.env.OM_INTEGRATION_QUEUE_NAME?.trim()\n const appRoot = process.env.OM_INTEGRATION_APP_ROOT?.trim()\n const jobLimit = Number.parseInt(process.env.OM_INTEGRATION_QUEUE_JOB_LIMIT || '100', 10) || 100\n if (!queueName || !appRoot) throw new Error('Missing queue drain environment')\n\n const processed = await drainQueueFromAppRoot(queueName, {\n appRoot: path.resolve(appRoot),\n jobLimit,\n queueBaseDir: process.env.QUEUE_BASE_DIR,\n })\n console.log(JSON.stringify({ processed }))\n}\n\nconst currentFile = fileURLToPath(import.meta.url)\nconst invokedFile = process.argv[1] ? path.resolve(process.argv[1]) : null\n\nif (invokedFile === currentFile) {\n runQueueDrainFromEnv()\n .then(() => {\n process.exit(0)\n })\n .catch((error) => {\n console.error(error)\n process.exit(1)\n })\n}\n"],
5
+ "mappings": "AAAA,OAAO,UAAU;AACjB,SAAS,qBAAqB;AAC9B,SAAS,4BAA4B;AACrC,SAAS,8BAA8B;AACvC,SAAS,mBAAmB;AAU5B,MAAM,iBAAiB,oBAAI,IAAoC;AAE/D,SAAS,iBAAiB,SAAyC;AACjE,QAAM,kBAAkB,KAAK,QAAQ,OAAO;AAC5C,QAAM,SAAS,eAAe,IAAI,eAAe;AACjD,MAAI,OAAQ,QAAO;AACnB,QAAM,UAAU,qBAAqB,eAAe;AACpD,iBAAe,IAAI,iBAAiB,OAAO;AAC3C,SAAO;AACT;AAEA,eAAsB,sBACpB,WACA,SACiB;AACjB,QAAM,OAAO,MAAM,iBAAiB,QAAQ,OAAO;AACnD,QAAM,SAAS,KAAK,QACjB,QAAQ,CAAC,WAAW,OAAO,WAAW,CAAC,CAAC,EACxC,KAAK,CAAC,UAAU,MAAM,UAAU,SAAS;AAC5C,MAAI,CAAC,OAAQ,QAAO;AAEpB,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,QAAQ,YAAY,WAAW,SAAS;AAAA,IAC5C,SAAS,KAAK;AAAA,MACZ,QAAQ,cAAc,KAAK,KACxB,QAAQ,IAAI,gBAAgB,KAAK,KACjC,KAAK,QAAQ,QAAQ,SAAS,gBAAgB;AAAA,IACnD;AAAA,IACA,aAAa;AAAA,EACf,CAAC;AACD,QAAM,UAAU,CAAc,SAAoB,UAAU,QAAQ,IAAI;AAExE,MAAI;AACF,QAAI,gBAAgB;AACpB,WAAO,MAAM;AACX,YAAM,SAAS,MAAM,MAAM;AAAA,QACzB,OAAO,KAAK,QAAQ;AAClB,gBAAM,QAAQ,QAAQ,OAAO,QAAQ,KAAK,EAAE,GAAG,KAAK,QAAQ,CAAC,CAAC;AAAA,QAChE;AAAA,QACA,EAAE,OAAO,QAAQ,SAAS;AAAA,MAC5B;AACA,YAAM,UAAU,OAAO,YAAY,OAAO;AAC1C,uBAAiB;AACjB,UAAI,YAAY,EAAG,QAAO;AAAA,IAC5B;AAAA,EACF,UAAE;AACA,UAAM,MAAM,MAAM;AAAA,EACpB;AACF;AAEA,eAAsB,uBAAsC;AAC1D,QAAM,YAAY,QAAQ,IAAI,2BAA2B,KAAK;AAC9D,QAAM,UAAU,QAAQ,IAAI,yBAAyB,KAAK;AAC1D,QAAM,WAAW,OAAO,SAAS,QAAQ,IAAI,kCAAkC,OAAO,EAAE,KAAK;AAC7F,MAAI,CAAC,aAAa,CAAC,QAAS,OAAM,IAAI,MAAM,iCAAiC;AAE7E,QAAM,YAAY,MAAM,sBAAsB,WAAW;AAAA,IACvD,SAAS,KAAK,QAAQ,OAAO;AAAA,IAC7B;AAAA,IACA,cAAc,QAAQ,IAAI;AAAA,EAC5B,CAAC;AACD,UAAQ,IAAI,KAAK,UAAU,EAAE,UAAU,CAAC,CAAC;AAC3C;AAEA,MAAM,cAAc,cAAc,YAAY,GAAG;AACjD,MAAM,cAAc,QAAQ,KAAK,CAAC,IAAI,KAAK,QAAQ,QAAQ,KAAK,CAAC,CAAC,IAAI;AAEtE,IAAI,gBAAgB,aAAa;AAC/B,uBAAqB,EAClB,KAAK,MAAM;AACV,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC,EACA,MAAM,CAAC,UAAU;AAChB,YAAQ,MAAM,KAAK;AACnB,YAAQ,KAAK,CAAC;AAAA,EAChB,CAAC;AACL;",
6
6
  "names": []
7
7
  }
@@ -22,7 +22,7 @@ function drainQueueInAppProcess(queueName, options) {
22
22
  OM_INTEGRATION_APP_ROOT: options.appRoot,
23
23
  OM_INTEGRATION_QUEUE_NAME: queueName,
24
24
  OM_INTEGRATION_QUEUE_JOB_LIMIT: String(options.jobLimit),
25
- QUEUE_BASE_DIR: path.resolve(options.appRoot, ".mercato/queue")
25
+ QUEUE_BASE_DIR: process.env.QUEUE_BASE_DIR?.trim() || path.resolve(options.appRoot, ".mercato/queue")
26
26
  },
27
27
  stdio: ["ignore", "pipe", "pipe"]
28
28
  });
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/helpers/integration/queue.ts"],
4
- "sourcesContent": ["import { spawn } from 'node:child_process'\nimport { createRequire } from 'node:module'\nimport path from 'node:path'\nimport { drainQueueFromAppRoot } from './queue-runner'\n\ntype DrainQueueOptions = {\n appRoot?: string\n jobLimit?: number\n}\n\nconst DEFAULT_JOB_LIMIT = 100\n\nfunction resolveAppRoot(input?: string): string {\n return path.resolve(input?.trim() || process.env.OM_TEST_APP_ROOT?.trim() || path.resolve(process.cwd(), 'apps/mercato'))\n}\n\nasync function drainQueueInCurrentProcess(queueName: string, options: Required<DrainQueueOptions>): Promise<number> {\n return drainQueueFromAppRoot(queueName, options)\n}\n\nfunction resolveAppRunnerPath(appRoot: string): string {\n const requireFromApp = createRequire(path.join(appRoot, 'package.json'))\n return requireFromApp.resolve('@open-mercato/core/helpers/integration/queue-runner')\n}\n\nfunction drainQueueInAppProcess(queueName: string, options: Required<DrainQueueOptions>): Promise<number> {\n return new Promise((resolve, reject) => {\n const child = spawn(process.execPath, [resolveAppRunnerPath(options.appRoot)], {\n cwd: options.appRoot,\n env: {\n ...process.env,\n OM_INTEGRATION_APP_ROOT: options.appRoot,\n OM_INTEGRATION_QUEUE_NAME: queueName,\n OM_INTEGRATION_QUEUE_JOB_LIMIT: String(options.jobLimit),\n QUEUE_BASE_DIR: path.resolve(options.appRoot, '.mercato/queue'),\n },\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n\n let stdout = ''\n let stderr = ''\n child.stdout.on('data', (chunk) => { stdout += chunk.toString() })\n child.stderr.on('data', (chunk) => { stderr += chunk.toString() })\n child.on('error', reject)\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`Queue drain failed for \"${queueName}\" in ${options.appRoot} (exit ${code}).\\n${stderr || stdout}`))\n return\n }\n const lastLine = stdout.trim().split(/\\r?\\n/).reverse().find((line) => line.trim().startsWith('{')) ?? '{}'\n try {\n const parsed = JSON.parse(lastLine) as { processed?: unknown }\n resolve(Number(parsed.processed ?? 0))\n } catch {\n resolve(0)\n }\n })\n })\n}\n\nexport async function drainIntegrationQueue(queueName: string, options: DrainQueueOptions = {}): Promise<number> {\n const resolved = {\n appRoot: resolveAppRoot(options.appRoot),\n jobLimit: options.jobLimit ?? DEFAULT_JOB_LIMIT,\n }\n if (process.env.OM_TEST_APP_ROOT?.trim()) {\n return drainQueueInAppProcess(queueName, resolved)\n }\n return drainQueueInCurrentProcess(queueName, resolved)\n}\n"],
5
- "mappings": "AAAA,SAAS,aAAa;AACtB,SAAS,qBAAqB;AAC9B,OAAO,UAAU;AACjB,SAAS,6BAA6B;AAOtC,MAAM,oBAAoB;AAE1B,SAAS,eAAe,OAAwB;AAC9C,SAAO,KAAK,QAAQ,OAAO,KAAK,KAAK,QAAQ,IAAI,kBAAkB,KAAK,KAAK,KAAK,QAAQ,QAAQ,IAAI,GAAG,cAAc,CAAC;AAC1H;AAEA,eAAe,2BAA2B,WAAmB,SAAuD;AAClH,SAAO,sBAAsB,WAAW,OAAO;AACjD;AAEA,SAAS,qBAAqB,SAAyB;AACrD,QAAM,iBAAiB,cAAc,KAAK,KAAK,SAAS,cAAc,CAAC;AACvE,SAAO,eAAe,QAAQ,qDAAqD;AACrF;AAEA,SAAS,uBAAuB,WAAmB,SAAuD;AACxG,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,QAAQ,MAAM,QAAQ,UAAU,CAAC,qBAAqB,QAAQ,OAAO,CAAC,GAAG;AAAA,MAC7E,KAAK,QAAQ;AAAA,MACb,KAAK;AAAA,QACH,GAAG,QAAQ;AAAA,QACX,yBAAyB,QAAQ;AAAA,QACjC,2BAA2B;AAAA,QAC3B,gCAAgC,OAAO,QAAQ,QAAQ;AAAA,QACvD,gBAAgB,KAAK,QAAQ,QAAQ,SAAS,gBAAgB;AAAA,MAChE;AAAA,MACA,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,IAClC,CAAC;AAED,QAAI,SAAS;AACb,QAAI,SAAS;AACb,UAAM,OAAO,GAAG,QAAQ,CAAC,UAAU;AAAE,gBAAU,MAAM,SAAS;AAAA,IAAE,CAAC;AACjE,UAAM,OAAO,GAAG,QAAQ,CAAC,UAAU;AAAE,gBAAU,MAAM,SAAS;AAAA,IAAE,CAAC;AACjE,UAAM,GAAG,SAAS,MAAM;AACxB,UAAM,GAAG,SAAS,CAAC,SAAS;AAC1B,UAAI,SAAS,GAAG;AACd,eAAO,IAAI,MAAM,2BAA2B,SAAS,QAAQ,QAAQ,OAAO,UAAU,IAAI;AAAA,EAAO,UAAU,MAAM,EAAE,CAAC;AACpH;AAAA,MACF;AACA,YAAM,WAAW,OAAO,KAAK,EAAE,MAAM,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,KAAK,KAAK,EAAE,WAAW,GAAG,CAAC,KAAK;AACvG,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,QAAQ;AAClC,gBAAQ,OAAO,OAAO,aAAa,CAAC,CAAC;AAAA,MACvC,QAAQ;AACN,gBAAQ,CAAC;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;AAEA,eAAsB,sBAAsB,WAAmB,UAA6B,CAAC,GAAoB;AAC/G,QAAM,WAAW;AAAA,IACf,SAAS,eAAe,QAAQ,OAAO;AAAA,IACvC,UAAU,QAAQ,YAAY;AAAA,EAChC;AACA,MAAI,QAAQ,IAAI,kBAAkB,KAAK,GAAG;AACxC,WAAO,uBAAuB,WAAW,QAAQ;AAAA,EACnD;AACA,SAAO,2BAA2B,WAAW,QAAQ;AACvD;",
4
+ "sourcesContent": ["import { spawn } from 'node:child_process'\nimport { createRequire } from 'node:module'\nimport path from 'node:path'\nimport { drainQueueFromAppRoot } from './queue-runner'\n\ntype DrainQueueOptions = {\n appRoot?: string\n jobLimit?: number\n}\n\nconst DEFAULT_JOB_LIMIT = 100\n\nfunction resolveAppRoot(input?: string): string {\n return path.resolve(input?.trim() || process.env.OM_TEST_APP_ROOT?.trim() || path.resolve(process.cwd(), 'apps/mercato'))\n}\n\nasync function drainQueueInCurrentProcess(queueName: string, options: Required<DrainQueueOptions>): Promise<number> {\n return drainQueueFromAppRoot(queueName, options)\n}\n\nfunction resolveAppRunnerPath(appRoot: string): string {\n const requireFromApp = createRequire(path.join(appRoot, 'package.json'))\n return requireFromApp.resolve('@open-mercato/core/helpers/integration/queue-runner')\n}\n\nfunction drainQueueInAppProcess(queueName: string, options: Required<DrainQueueOptions>): Promise<number> {\n return new Promise((resolve, reject) => {\n const child = spawn(process.execPath, [resolveAppRunnerPath(options.appRoot)], {\n cwd: options.appRoot,\n env: {\n ...process.env,\n OM_INTEGRATION_APP_ROOT: options.appRoot,\n OM_INTEGRATION_QUEUE_NAME: queueName,\n OM_INTEGRATION_QUEUE_JOB_LIMIT: String(options.jobLimit),\n QUEUE_BASE_DIR: process.env.QUEUE_BASE_DIR?.trim() || path.resolve(options.appRoot, '.mercato/queue'),\n },\n stdio: ['ignore', 'pipe', 'pipe'],\n })\n\n let stdout = ''\n let stderr = ''\n child.stdout.on('data', (chunk) => { stdout += chunk.toString() })\n child.stderr.on('data', (chunk) => { stderr += chunk.toString() })\n child.on('error', reject)\n child.on('close', (code) => {\n if (code !== 0) {\n reject(new Error(`Queue drain failed for \"${queueName}\" in ${options.appRoot} (exit ${code}).\\n${stderr || stdout}`))\n return\n }\n const lastLine = stdout.trim().split(/\\r?\\n/).reverse().find((line) => line.trim().startsWith('{')) ?? '{}'\n try {\n const parsed = JSON.parse(lastLine) as { processed?: unknown }\n resolve(Number(parsed.processed ?? 0))\n } catch {\n resolve(0)\n }\n })\n })\n}\n\nexport async function drainIntegrationQueue(queueName: string, options: DrainQueueOptions = {}): Promise<number> {\n const resolved = {\n appRoot: resolveAppRoot(options.appRoot),\n jobLimit: options.jobLimit ?? DEFAULT_JOB_LIMIT,\n }\n if (process.env.OM_TEST_APP_ROOT?.trim()) {\n return drainQueueInAppProcess(queueName, resolved)\n }\n return drainQueueInCurrentProcess(queueName, resolved)\n}\n"],
5
+ "mappings": "AAAA,SAAS,aAAa;AACtB,SAAS,qBAAqB;AAC9B,OAAO,UAAU;AACjB,SAAS,6BAA6B;AAOtC,MAAM,oBAAoB;AAE1B,SAAS,eAAe,OAAwB;AAC9C,SAAO,KAAK,QAAQ,OAAO,KAAK,KAAK,QAAQ,IAAI,kBAAkB,KAAK,KAAK,KAAK,QAAQ,QAAQ,IAAI,GAAG,cAAc,CAAC;AAC1H;AAEA,eAAe,2BAA2B,WAAmB,SAAuD;AAClH,SAAO,sBAAsB,WAAW,OAAO;AACjD;AAEA,SAAS,qBAAqB,SAAyB;AACrD,QAAM,iBAAiB,cAAc,KAAK,KAAK,SAAS,cAAc,CAAC;AACvE,SAAO,eAAe,QAAQ,qDAAqD;AACrF;AAEA,SAAS,uBAAuB,WAAmB,SAAuD;AACxG,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,QAAQ,MAAM,QAAQ,UAAU,CAAC,qBAAqB,QAAQ,OAAO,CAAC,GAAG;AAAA,MAC7E,KAAK,QAAQ;AAAA,MACb,KAAK;AAAA,QACH,GAAG,QAAQ;AAAA,QACX,yBAAyB,QAAQ;AAAA,QACjC,2BAA2B;AAAA,QAC3B,gCAAgC,OAAO,QAAQ,QAAQ;AAAA,QACvD,gBAAgB,QAAQ,IAAI,gBAAgB,KAAK,KAAK,KAAK,QAAQ,QAAQ,SAAS,gBAAgB;AAAA,MACtG;AAAA,MACA,OAAO,CAAC,UAAU,QAAQ,MAAM;AAAA,IAClC,CAAC;AAED,QAAI,SAAS;AACb,QAAI,SAAS;AACb,UAAM,OAAO,GAAG,QAAQ,CAAC,UAAU;AAAE,gBAAU,MAAM,SAAS;AAAA,IAAE,CAAC;AACjE,UAAM,OAAO,GAAG,QAAQ,CAAC,UAAU;AAAE,gBAAU,MAAM,SAAS;AAAA,IAAE,CAAC;AACjE,UAAM,GAAG,SAAS,MAAM;AACxB,UAAM,GAAG,SAAS,CAAC,SAAS;AAC1B,UAAI,SAAS,GAAG;AACd,eAAO,IAAI,MAAM,2BAA2B,SAAS,QAAQ,QAAQ,OAAO,UAAU,IAAI;AAAA,EAAO,UAAU,MAAM,EAAE,CAAC;AACpH;AAAA,MACF;AACA,YAAM,WAAW,OAAO,KAAK,EAAE,MAAM,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,SAAS,KAAK,KAAK,EAAE,WAAW,GAAG,CAAC,KAAK;AACvG,UAAI;AACF,cAAM,SAAS,KAAK,MAAM,QAAQ;AAClC,gBAAQ,OAAO,OAAO,aAAa,CAAC,CAAC;AAAA,MACvC,QAAQ;AACN,gBAAQ,CAAC;AAAA,MACX;AAAA,IACF,CAAC;AAAA,EACH,CAAC;AACH;AAEA,eAAsB,sBAAsB,WAAmB,UAA6B,CAAC,GAAoB;AAC/G,QAAM,WAAW;AAAA,IACf,SAAS,eAAe,QAAQ,OAAO;AAAA,IACvC,UAAU,QAAQ,YAAY;AAAA,EAChC;AACA,MAAI,QAAQ,IAAI,kBAAkB,KAAK,GAAG;AACxC,WAAO,uBAAuB,WAAW,QAAQ;AAAA,EACnD;AACA,SAAO,2BAA2B,WAAW,QAAQ;AACvD;",
6
6
  "names": []
7
7
  }
@@ -637,7 +637,30 @@ async function createSalesDocument(page, options) {
637
637
  await openSalesDocumentPage(page, id, options.kind);
638
638
  return id;
639
639
  }
640
- await createButton.click();
640
+ let clicked = false;
641
+ for (let attempt = 0; attempt < 3; attempt += 1) {
642
+ try {
643
+ await page.waitForLoadState("networkidle", { timeout: 2e3 }).catch(() => {
644
+ });
645
+ const liveButton = page.getByRole("button", { name: /^Create$/i }).first();
646
+ if (!await liveButton.isVisible().catch(() => false)) break;
647
+ if (!await liveButton.isEnabled().catch(() => false)) {
648
+ await page.waitForTimeout(300);
649
+ continue;
650
+ }
651
+ await liveButton.click({ timeout: 5e3 });
652
+ clicked = true;
653
+ break;
654
+ } catch {
655
+ await page.waitForTimeout(300);
656
+ }
657
+ }
658
+ if (!clicked) {
659
+ const token = await resolveFallbackToken();
660
+ const id = await createSalesDocumentFixture(page, token, options.kind, customerQuery, channelQuery, fixtureContext);
661
+ await openSalesDocumentPage(page, id, options.kind);
662
+ return id;
663
+ }
641
664
  const navigated = await page.waitForURL(
642
665
  new RegExp(
643
666
  `/backend/sales/(?:documents/[0-9a-f-]{36}\\?kind=${options.kind}|${options.kind === "order" ? "orders" : "quotes"}/[0-9a-f-]{36})$`,