@open-mercato/core 0.4.6-develop-e321a4e2a1 → 0.4.6-main-24e64eef39

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 (180) hide show
  1. package/AGENTS.md +0 -22
  2. package/dist/modules/api_docs/frontend/docs/api/page.js +1 -1
  3. package/dist/modules/api_docs/frontend/docs/api/page.js.map +2 -2
  4. package/dist/modules/attachments/api/library/[id]/route.js +1 -0
  5. package/dist/modules/attachments/api/library/[id]/route.js.map +2 -2
  6. package/dist/modules/attachments/components/AttachmentLibrary.js +1 -1
  7. package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
  8. package/dist/modules/attachments/lib/partitionEnv.js +1 -1
  9. package/dist/modules/attachments/lib/partitionEnv.js.map +2 -2
  10. package/dist/modules/auth/backend/users/page.js +1 -1
  11. package/dist/modules/auth/backend/users/page.js.map +2 -2
  12. package/dist/modules/auth/cli.js +1 -1
  13. package/dist/modules/auth/cli.js.map +2 -2
  14. package/dist/modules/auth/commands/users.js +1 -1
  15. package/dist/modules/auth/commands/users.js.map +2 -2
  16. package/dist/modules/business_rules/components/utils/formHelpers.js +1 -1
  17. package/dist/modules/business_rules/components/utils/formHelpers.js.map +2 -2
  18. package/dist/modules/catalog/backend/catalog/products/create/page.js +1 -1
  19. package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
  20. package/dist/modules/catalog/commands/products.js +1 -1
  21. package/dist/modules/catalog/commands/products.js.map +2 -2
  22. package/dist/modules/catalog/commands/shared.js +1 -1
  23. package/dist/modules/catalog/commands/shared.js.map +2 -2
  24. package/dist/modules/catalog/components/PriceKindSettings.js +1 -1
  25. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  26. package/dist/modules/catalog/components/products/productForm.js +1 -1
  27. package/dist/modules/catalog/components/products/productForm.js.map +2 -2
  28. package/dist/modules/configs/lib/upgrade-actions.js.map +1 -1
  29. package/dist/modules/currencies/services/providers/raiffeisen.js +1 -1
  30. package/dist/modules/currencies/services/providers/raiffeisen.js.map +2 -2
  31. package/dist/modules/customers/backend/customers/companies/page.js +3 -3
  32. package/dist/modules/customers/backend/customers/companies/page.js.map +2 -2
  33. package/dist/modules/customers/backend/customers/deals/page.js +3 -3
  34. package/dist/modules/customers/backend/customers/deals/page.js.map +2 -2
  35. package/dist/modules/customers/backend/customers/people/page.js +3 -3
  36. package/dist/modules/customers/backend/customers/people/page.js.map +2 -2
  37. package/dist/modules/customers/cli.js +2 -2
  38. package/dist/modules/customers/cli.js.map +2 -2
  39. package/dist/modules/customers/lib/detailHelpers.js +1 -1
  40. package/dist/modules/customers/lib/detailHelpers.js.map +2 -2
  41. package/dist/modules/entities/cli.js +1 -1
  42. package/dist/modules/entities/cli.js.map +2 -2
  43. package/dist/modules/entities/lib/field-definitions.js +1 -1
  44. package/dist/modules/entities/lib/field-definitions.js.map +2 -2
  45. package/dist/modules/entities/lib/install-from-ce.js +1 -1
  46. package/dist/modules/entities/lib/install-from-ce.js.map +2 -2
  47. package/dist/modules/inbox_ops/lib/emailParser.js +1 -1
  48. package/dist/modules/inbox_ops/lib/emailParser.js.map +2 -2
  49. package/dist/modules/inbox_ops/widgets/notifications/ProposalCreatedRenderer.js +0 -8
  50. package/dist/modules/inbox_ops/widgets/notifications/ProposalCreatedRenderer.js.map +2 -2
  51. package/dist/modules/perspectives/services/perspectiveService.js +1 -1
  52. package/dist/modules/perspectives/services/perspectiveService.js.map +2 -2
  53. package/dist/modules/planner/backend/planner/availability-rulesets/page.js +3 -3
  54. package/dist/modules/planner/backend/planner/availability-rulesets/page.js.map +2 -2
  55. package/dist/modules/query_index/components/QueryIndexesTable.js +7 -7
  56. package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
  57. package/dist/modules/query_index/lib/engine.js +1 -1
  58. package/dist/modules/query_index/lib/engine.js.map +2 -2
  59. package/dist/modules/resources/backend/resources/resource-types/page.js +2 -2
  60. package/dist/modules/resources/backend/resources/resource-types/page.js.map +2 -2
  61. package/dist/modules/resources/backend/resources/resources/page.js +3 -3
  62. package/dist/modules/resources/backend/resources/resources/page.js.map +2 -2
  63. package/dist/modules/resources/commands/resources.js +1 -1
  64. package/dist/modules/resources/commands/resources.js.map +2 -2
  65. package/dist/modules/resources/lib/seeds.js +1 -1
  66. package/dist/modules/resources/lib/seeds.js.map +2 -2
  67. package/dist/modules/sales/api/dashboard/widgets/new-orders/route.js +1 -1
  68. package/dist/modules/sales/api/dashboard/widgets/new-orders/route.js.map +2 -2
  69. package/dist/modules/sales/api/dashboard/widgets/new-quotes/route.js +1 -1
  70. package/dist/modules/sales/api/dashboard/widgets/new-quotes/route.js.map +2 -2
  71. package/dist/modules/sales/backend/sales/channels/page.js +3 -3
  72. package/dist/modules/sales/backend/sales/channels/page.js.map +2 -2
  73. package/dist/modules/sales/commands/documents.js +2 -2
  74. package/dist/modules/sales/commands/documents.js.map +2 -2
  75. package/dist/modules/sales/components/channels/offerTableUtils.js +2 -3
  76. package/dist/modules/sales/components/channels/offerTableUtils.js.map +2 -2
  77. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +4 -4
  78. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  79. package/dist/modules/sales/components/documents/ShipmentDialog.js +1 -1
  80. package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
  81. package/dist/modules/sales/lib/shipments/snapshots.js.map +1 -1
  82. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +0 -8
  83. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +2 -2
  84. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +0 -8
  85. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +2 -2
  86. package/dist/modules/staff/backend/staff/leave-requests/page.js +3 -3
  87. package/dist/modules/staff/backend/staff/leave-requests/page.js.map +2 -2
  88. package/dist/modules/staff/backend/staff/my-leave-requests/page.js +3 -3
  89. package/dist/modules/staff/backend/staff/my-leave-requests/page.js.map +2 -2
  90. package/dist/modules/staff/backend/staff/team-members/page.js +3 -3
  91. package/dist/modules/staff/backend/staff/team-members/page.js.map +2 -2
  92. package/dist/modules/staff/backend/staff/team-roles/page.js +2 -2
  93. package/dist/modules/staff/backend/staff/team-roles/page.js.map +2 -2
  94. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js +3 -3
  95. package/dist/modules/staff/backend/staff/teams/[id]/edit/page.js.map +2 -2
  96. package/dist/modules/staff/backend/staff/teams/page.js +2 -2
  97. package/dist/modules/staff/backend/staff/teams/page.js.map +2 -2
  98. package/dist/modules/workflows/backend/instances/page.js +2 -2
  99. package/dist/modules/workflows/backend/instances/page.js.map +2 -2
  100. package/dist/modules/workflows/backend/tasks/page.js +1 -1
  101. package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
  102. package/dist/modules/workflows/components/DefinitionTriggersEditor.js +1 -1
  103. package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +2 -2
  104. package/dist/modules/workflows/lib/graph-utils.js +1 -1
  105. package/dist/modules/workflows/lib/graph-utils.js.map +2 -2
  106. package/package.json +2 -2
  107. package/src/modules/api_docs/frontend/docs/api/page.tsx +1 -1
  108. package/src/modules/attachments/api/library/[id]/route.ts +1 -0
  109. package/src/modules/attachments/components/AttachmentLibrary.tsx +1 -1
  110. package/src/modules/attachments/lib/partitionEnv.ts +1 -1
  111. package/src/modules/auth/backend/users/page.tsx +1 -1
  112. package/src/modules/auth/cli.ts +1 -1
  113. package/src/modules/auth/commands/users.ts +1 -1
  114. package/src/modules/business_rules/components/utils/formHelpers.ts +1 -1
  115. package/src/modules/catalog/backend/catalog/products/create/page.tsx +1 -1
  116. package/src/modules/catalog/commands/products.ts +1 -1
  117. package/src/modules/catalog/commands/shared.ts +1 -1
  118. package/src/modules/catalog/components/PriceKindSettings.tsx +1 -1
  119. package/src/modules/catalog/components/products/productForm.ts +1 -1
  120. package/src/modules/configs/lib/upgrade-actions.ts +1 -1
  121. package/src/modules/currencies/services/providers/raiffeisen.ts +1 -1
  122. package/src/modules/customers/backend/customers/companies/page.tsx +3 -3
  123. package/src/modules/customers/backend/customers/deals/page.tsx +3 -3
  124. package/src/modules/customers/backend/customers/people/page.tsx +3 -3
  125. package/src/modules/customers/cli.ts +2 -2
  126. package/src/modules/customers/lib/detailHelpers.ts +1 -1
  127. package/src/modules/entities/cli.ts +1 -1
  128. package/src/modules/entities/lib/field-definitions.ts +1 -1
  129. package/src/modules/entities/lib/install-from-ce.ts +1 -1
  130. package/src/modules/inbox_ops/lib/emailParser.ts +1 -1
  131. package/src/modules/inbox_ops/widgets/notifications/ProposalCreatedRenderer.tsx +0 -8
  132. package/src/modules/perspectives/services/perspectiveService.ts +1 -1
  133. package/src/modules/planner/backend/planner/availability-rulesets/page.tsx +4 -3
  134. package/src/modules/query_index/components/QueryIndexesTable.tsx +7 -7
  135. package/src/modules/query_index/lib/engine.ts +1 -1
  136. package/src/modules/resources/backend/resources/resource-types/page.tsx +3 -2
  137. package/src/modules/resources/backend/resources/resources/page.tsx +3 -3
  138. package/src/modules/resources/commands/resources.ts +1 -1
  139. package/src/modules/resources/lib/seeds.ts +1 -1
  140. package/src/modules/sales/api/dashboard/widgets/new-orders/route.ts +1 -1
  141. package/src/modules/sales/api/dashboard/widgets/new-quotes/route.ts +1 -1
  142. package/src/modules/sales/backend/sales/channels/page.tsx +3 -3
  143. package/src/modules/sales/commands/documents.ts +2 -2
  144. package/src/modules/sales/components/channels/offerTableUtils.tsx +2 -3
  145. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +4 -4
  146. package/src/modules/sales/components/documents/ShipmentDialog.tsx +1 -1
  147. package/src/modules/sales/lib/shipments/snapshots.ts +1 -1
  148. package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +0 -8
  149. package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +0 -8
  150. package/src/modules/staff/backend/staff/leave-requests/page.tsx +3 -3
  151. package/src/modules/staff/backend/staff/my-leave-requests/page.tsx +3 -3
  152. package/src/modules/staff/backend/staff/team-members/page.tsx +3 -3
  153. package/src/modules/staff/backend/staff/team-roles/page.tsx +2 -2
  154. package/src/modules/staff/backend/staff/teams/[id]/edit/page.tsx +4 -3
  155. package/src/modules/staff/backend/staff/teams/page.tsx +3 -2
  156. package/src/modules/workflows/backend/instances/page.tsx +2 -2
  157. package/src/modules/workflows/backend/tasks/page.tsx +1 -1
  158. package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +1 -1
  159. package/src/modules/workflows/lib/graph-utils.ts +1 -1
  160. package/dist/modules/integrations/acl.js +0 -8
  161. package/dist/modules/integrations/acl.js.map +0 -7
  162. package/dist/modules/integrations/data/enrichers.js +0 -72
  163. package/dist/modules/integrations/data/enrichers.js.map +0 -7
  164. package/dist/modules/integrations/data/entities.js +0 -63
  165. package/dist/modules/integrations/data/entities.js.map +0 -7
  166. package/dist/modules/integrations/index.js +0 -9
  167. package/dist/modules/integrations/index.js.map +0 -7
  168. package/dist/modules/integrations/setup.js +0 -13
  169. package/dist/modules/integrations/setup.js.map +0 -7
  170. package/dist/modules/integrations/widgets/injection/external-ids/widget.client.js +0 -69
  171. package/dist/modules/integrations/widgets/injection/external-ids/widget.client.js.map +0 -7
  172. package/dist/modules/integrations/widgets/injection-table.js +0 -13
  173. package/dist/modules/integrations/widgets/injection-table.js.map +0 -7
  174. package/src/modules/integrations/acl.ts +0 -4
  175. package/src/modules/integrations/data/enrichers.ts +0 -98
  176. package/src/modules/integrations/data/entities.ts +0 -46
  177. package/src/modules/integrations/index.ts +0 -5
  178. package/src/modules/integrations/setup.ts +0 -11
  179. package/src/modules/integrations/widgets/injection/external-ids/widget.client.tsx +0 -94
  180. package/src/modules/integrations/widgets/injection-table.ts +0 -17
@@ -7,7 +7,7 @@ import type { PluggableList } from 'unified'
7
7
  import { useRouter } from 'next/navigation'
8
8
  import type { ColumnDef } from '@tanstack/react-table'
9
9
  import { Page, PageBody } from '@open-mercato/ui/backend/Page'
10
- import { DataTable, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'
10
+ import { DataTable } from '@open-mercato/ui/backend/DataTable'
11
11
  import { RowActions } from '@open-mercato/ui/backend/RowActions'
12
12
  import { Button } from '@open-mercato/ui/primitives/button'
13
13
  import { readApiResultOrThrow, apiCall } from '@open-mercato/ui/backend/utils/apiCall'
@@ -394,7 +394,7 @@ function mapApiTeamRole(item: Record<string, unknown>): TeamRoleApiRow {
394
394
  : null
395
395
  const teamName = typeof team?.name === 'string' ? team.name : null
396
396
  const memberCount = typeof item.memberCount === 'number' ? item.memberCount : 0
397
- return withDataTableNamespaces({ id, name, description, updatedAt, teamId, teamName, memberCount }, item)
397
+ return { id, name, description, updatedAt, teamId, teamName, memberCount }
398
398
  }
399
399
 
400
400
  function buildTeamRoleRows(items: TeamRoleApiRow[], unassignedLabel: string): TeamRoleRow[] {
@@ -7,7 +7,7 @@ import type { ColumnDef, SortingState } from '@tanstack/react-table'
7
7
  import { Page, PageBody } from '@open-mercato/ui/backend/Page'
8
8
  import { readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'
9
9
  import { updateCrud, deleteCrud } from '@open-mercato/ui/backend/utils/crud'
10
- import { DataTable, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'
10
+ import { DataTable } from '@open-mercato/ui/backend/DataTable'
11
11
  import { RowActions } from '@open-mercato/ui/backend/RowActions'
12
12
  import { Button } from '@open-mercato/ui/primitives/button'
13
13
  import { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'
@@ -424,7 +424,7 @@ function mapApiTeamMember(item: Record<string, unknown>): TeamMemberRow {
424
424
  : typeof item.team_id === 'string'
425
425
  ? item.team_id
426
426
  : null
427
- return withDataTableNamespaces({
427
+ return {
428
428
  id,
429
429
  displayName,
430
430
  description,
@@ -434,6 +434,7 @@ function mapApiTeamMember(item: Record<string, unknown>): TeamMemberRow {
434
434
  isActive,
435
435
  updatedAt,
436
436
  teamId,
437
- }, item)
437
+ }
438
438
  }
439
439
 
440
+
@@ -7,7 +7,7 @@ import type { PluggableList } from 'unified'
7
7
  import { useRouter } from 'next/navigation'
8
8
  import type { ColumnDef, SortingState } from '@tanstack/react-table'
9
9
  import { Page, PageBody } from '@open-mercato/ui/backend/Page'
10
- import { DataTable, withDataTableNamespaces } from '@open-mercato/ui/backend/DataTable'
10
+ import { DataTable } from '@open-mercato/ui/backend/DataTable'
11
11
  import { RowActions } from '@open-mercato/ui/backend/RowActions'
12
12
  import { Button } from '@open-mercato/ui/primitives/button'
13
13
  import { BooleanIcon } from '@open-mercato/ui/backend/ValueIcons'
@@ -317,6 +317,7 @@ function mapApiTeam(item: Record<string, unknown>): TeamRow {
317
317
  : typeof item.member_count === 'number'
318
318
  ? item.member_count
319
319
  : 0
320
- return withDataTableNamespaces({ id, name, description, isActive, updatedAt, memberCount }, item)
320
+ return { id, name, description, isActive, updatedAt, memberCount }
321
321
  }
322
322
 
323
+
@@ -288,7 +288,7 @@ export default function WorkflowInstancesListPage() {
288
288
  items.push({
289
289
  id: 'cancel',
290
290
  label: t('workflows.instances.actions.cancel'),
291
- onSelect: () => void handleCancel(row.original.id, row.original.workflowId),
291
+ onSelect: () => handleCancel(row.original.id, row.original.workflowId),
292
292
  })
293
293
  }
294
294
 
@@ -296,7 +296,7 @@ export default function WorkflowInstancesListPage() {
296
296
  items.push({
297
297
  id: 'retry',
298
298
  label: t('workflows.instances.actions.retry'),
299
- onSelect: () => void handleRetry(row.original.id, row.original.workflowId),
299
+ onSelect: () => handleRetry(row.original.id, row.original.workflowId),
300
300
  })
301
301
  }
302
302
 
@@ -296,7 +296,7 @@ export default function UserTasksListPage() {
296
296
  items.push({
297
297
  id: 'claim',
298
298
  label: t('workflows.tasks.actions.claim'),
299
- onSelect: () => void handleClaim(row.original.id, row.original.taskName),
299
+ onSelect: () => handleClaim(row.original.id, row.original.taskName),
300
300
  })
301
301
  }
302
302
 
@@ -93,7 +93,7 @@ export function DefinitionTriggersEditor({
93
93
  return name
94
94
  .toLowerCase()
95
95
  .replace(/[^a-z0-9]+/g, '_')
96
- .replace(/(?:^_+|_+$)/g, '')
96
+ .replace(/^_+|_+$/g, '')
97
97
  .substring(0, 50) || `trigger_${Date.now()}`
98
98
  }, [])
99
99
 
@@ -631,7 +631,7 @@ export function sanitizeId(input: string): string {
631
631
  .toLowerCase()
632
632
  .replace(/[^a-z0-9_-]/g, '_')
633
633
  .replace(/_{2,}/g, '_') // Replace multiple underscores with single
634
- .replace(/(?:^_|_$)/g, '') // Remove leading/trailing underscores
634
+ .replace(/^_|_$/g, '') // Remove leading/trailing underscores
635
635
  }
636
636
 
637
637
  /**
@@ -1,8 +0,0 @@
1
- const features = [
2
- { id: "integrations.view", title: "View integrations and external ID mappings", module: "integrations" },
3
- { id: "integrations.manage", title: "Manage integration configurations", module: "integrations" }
4
- ];
5
- export {
6
- features
7
- };
8
- //# sourceMappingURL=acl.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/modules/integrations/acl.ts"],
4
- "sourcesContent": ["export const features = [\n { id: 'integrations.view', title: 'View integrations and external ID mappings', module: 'integrations' },\n { id: 'integrations.manage', title: 'Manage integration configurations', module: 'integrations' },\n]\n"],
5
- "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,EAAE,IAAI,qBAAqB,OAAO,8CAA8C,QAAQ,eAAe;AAAA,EACvG,EAAE,IAAI,uBAAuB,OAAO,qCAAqC,QAAQ,eAAe;AAClG;",
6
- "names": []
7
- }
@@ -1,72 +0,0 @@
1
- import { getIntegration } from "@open-mercato/shared/modules/integrations/types";
2
- import { SyncExternalIdMapping } from "./entities.js";
3
- function buildIntegrationData(mappings) {
4
- const data = {};
5
- for (const mapping of mappings) {
6
- const definition = getIntegration(mapping.integrationId);
7
- data[mapping.integrationId] = {
8
- externalId: mapping.externalId,
9
- externalUrl: definition?.buildExternalUrl?.(mapping.externalId),
10
- lastSyncedAt: mapping.lastSyncedAt?.toISOString(),
11
- syncStatus: mapping.syncStatus
12
- };
13
- }
14
- return data;
15
- }
16
- const externalIdMappingEnricher = {
17
- id: "integrations.external-id-mapping",
18
- targetEntity: "*",
19
- features: ["integrations.view"],
20
- priority: 10,
21
- timeout: 500,
22
- critical: false,
23
- fallback: {},
24
- async enrichOne(record, context) {
25
- const em = context.em.fork();
26
- const targetEntity = context.targetEntity;
27
- if (!targetEntity) return { ...record, _integrations: {} };
28
- const mappings = await em.find(SyncExternalIdMapping, {
29
- internalEntityType: targetEntity,
30
- internalEntityId: record.id,
31
- organizationId: context.organizationId,
32
- deletedAt: null
33
- });
34
- if (mappings.length === 0) return { ...record, _integrations: {} };
35
- return {
36
- ...record,
37
- _integrations: buildIntegrationData(mappings)
38
- };
39
- },
40
- async enrichMany(records, context) {
41
- const em = context.em.fork();
42
- const targetEntity = context.targetEntity;
43
- if (!targetEntity || records.length === 0) return records.map((r) => ({ ...r, _integrations: {} }));
44
- const recordIds = records.map((r) => r.id);
45
- const allMappings = await em.find(SyncExternalIdMapping, {
46
- internalEntityType: targetEntity,
47
- internalEntityId: { $in: recordIds },
48
- organizationId: context.organizationId,
49
- deletedAt: null
50
- });
51
- if (allMappings.length === 0) return records.map((r) => ({ ...r, _integrations: {} }));
52
- const mappingsByRecord = /* @__PURE__ */ new Map();
53
- for (const mapping of allMappings) {
54
- const list = mappingsByRecord.get(mapping.internalEntityId) ?? [];
55
- list.push(mapping);
56
- mappingsByRecord.set(mapping.internalEntityId, list);
57
- }
58
- return records.map((record) => {
59
- const mappings = mappingsByRecord.get(record.id);
60
- if (!mappings || mappings.length === 0) return { ...record, _integrations: {} };
61
- return {
62
- ...record,
63
- _integrations: buildIntegrationData(mappings)
64
- };
65
- });
66
- }
67
- };
68
- const enrichers = [externalIdMappingEnricher];
69
- export {
70
- enrichers
71
- };
72
- //# sourceMappingURL=enrichers.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/modules/integrations/data/enrichers.ts"],
4
- "sourcesContent": ["/**\n * External ID Mapping Enricher\n *\n * Enriches any entity's API response with external integration ID mappings.\n * Adds `_integrations` namespace containing all external IDs for the record.\n *\n * Uses batch queries via `enrichMany` to prevent N+1.\n */\n\nimport type { ResponseEnricher, EnricherContext } from '@open-mercato/shared/lib/crud/response-enricher'\nimport type { ExternalIdEnrichment } from '@open-mercato/shared/modules/integrations/types'\nimport { getIntegration } from '@open-mercato/shared/modules/integrations/types'\nimport { SyncExternalIdMapping } from './entities'\n\ntype EntityRecord = Record<string, unknown> & { id: string }\n\nfunction buildIntegrationData(\n mappings: SyncExternalIdMapping[],\n): ExternalIdEnrichment['_integrations'] {\n const data: ExternalIdEnrichment['_integrations'] = {}\n\n for (const mapping of mappings) {\n const definition = getIntegration(mapping.integrationId)\n data[mapping.integrationId] = {\n externalId: mapping.externalId,\n externalUrl: definition?.buildExternalUrl?.(mapping.externalId),\n lastSyncedAt: mapping.lastSyncedAt?.toISOString(),\n syncStatus: mapping.syncStatus,\n }\n }\n\n return data\n}\n\nconst externalIdMappingEnricher: ResponseEnricher<EntityRecord, ExternalIdEnrichment> = {\n id: 'integrations.external-id-mapping',\n targetEntity: '*',\n features: ['integrations.view'],\n priority: 10,\n timeout: 500,\n critical: false,\n fallback: {},\n\n async enrichOne(record, context: EnricherContext & { targetEntity?: string }) {\n const em = (context.em as any).fork()\n const targetEntity = (context as any).targetEntity as string | undefined\n if (!targetEntity) return { ...record, _integrations: {} }\n\n const mappings: SyncExternalIdMapping[] = await em.find(SyncExternalIdMapping, {\n internalEntityType: targetEntity,\n internalEntityId: record.id,\n organizationId: context.organizationId,\n deletedAt: null,\n })\n\n if (mappings.length === 0) return { ...record, _integrations: {} }\n\n return {\n ...record,\n _integrations: buildIntegrationData(mappings),\n }\n },\n\n async enrichMany(records, context: EnricherContext & { targetEntity?: string }) {\n const em = (context.em as any).fork()\n const targetEntity = (context as any).targetEntity as string | undefined\n if (!targetEntity || records.length === 0) return records.map((r) => ({ ...r, _integrations: {} }))\n\n const recordIds = records.map((r) => r.id)\n const allMappings: SyncExternalIdMapping[] = await em.find(SyncExternalIdMapping, {\n internalEntityType: targetEntity,\n internalEntityId: { $in: recordIds },\n organizationId: context.organizationId,\n deletedAt: null,\n })\n\n if (allMappings.length === 0) return records.map((r) => ({ ...r, _integrations: {} }))\n\n const mappingsByRecord = new Map<string, SyncExternalIdMapping[]>()\n for (const mapping of allMappings) {\n const list = mappingsByRecord.get(mapping.internalEntityId) ?? []\n list.push(mapping)\n mappingsByRecord.set(mapping.internalEntityId, list)\n }\n\n return records.map((record) => {\n const mappings = mappingsByRecord.get(record.id)\n if (!mappings || mappings.length === 0) return { ...record, _integrations: {} }\n\n return {\n ...record,\n _integrations: buildIntegrationData(mappings),\n }\n })\n },\n}\n\nexport const enrichers: ResponseEnricher[] = [externalIdMappingEnricher]\n"],
5
- "mappings": "AAWA,SAAS,sBAAsB;AAC/B,SAAS,6BAA6B;AAItC,SAAS,qBACP,UACuC;AACvC,QAAM,OAA8C,CAAC;AAErD,aAAW,WAAW,UAAU;AAC9B,UAAM,aAAa,eAAe,QAAQ,aAAa;AACvD,SAAK,QAAQ,aAAa,IAAI;AAAA,MAC5B,YAAY,QAAQ;AAAA,MACpB,aAAa,YAAY,mBAAmB,QAAQ,UAAU;AAAA,MAC9D,cAAc,QAAQ,cAAc,YAAY;AAAA,MAChD,YAAY,QAAQ;AAAA,IACtB;AAAA,EACF;AAEA,SAAO;AACT;AAEA,MAAM,4BAAkF;AAAA,EACtF,IAAI;AAAA,EACJ,cAAc;AAAA,EACd,UAAU,CAAC,mBAAmB;AAAA,EAC9B,UAAU;AAAA,EACV,SAAS;AAAA,EACT,UAAU;AAAA,EACV,UAAU,CAAC;AAAA,EAEX,MAAM,UAAU,QAAQ,SAAsD;AAC5E,UAAM,KAAM,QAAQ,GAAW,KAAK;AACpC,UAAM,eAAgB,QAAgB;AACtC,QAAI,CAAC,aAAc,QAAO,EAAE,GAAG,QAAQ,eAAe,CAAC,EAAE;AAEzD,UAAM,WAAoC,MAAM,GAAG,KAAK,uBAAuB;AAAA,MAC7E,oBAAoB;AAAA,MACpB,kBAAkB,OAAO;AAAA,MACzB,gBAAgB,QAAQ;AAAA,MACxB,WAAW;AAAA,IACb,CAAC;AAED,QAAI,SAAS,WAAW,EAAG,QAAO,EAAE,GAAG,QAAQ,eAAe,CAAC,EAAE;AAEjE,WAAO;AAAA,MACL,GAAG;AAAA,MACH,eAAe,qBAAqB,QAAQ;AAAA,IAC9C;AAAA,EACF;AAAA,EAEA,MAAM,WAAW,SAAS,SAAsD;AAC9E,UAAM,KAAM,QAAQ,GAAW,KAAK;AACpC,UAAM,eAAgB,QAAgB;AACtC,QAAI,CAAC,gBAAgB,QAAQ,WAAW,EAAG,QAAO,QAAQ,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,eAAe,CAAC,EAAE,EAAE;AAElG,UAAM,YAAY,QAAQ,IAAI,CAAC,MAAM,EAAE,EAAE;AACzC,UAAM,cAAuC,MAAM,GAAG,KAAK,uBAAuB;AAAA,MAChF,oBAAoB;AAAA,MACpB,kBAAkB,EAAE,KAAK,UAAU;AAAA,MACnC,gBAAgB,QAAQ;AAAA,MACxB,WAAW;AAAA,IACb,CAAC;AAED,QAAI,YAAY,WAAW,EAAG,QAAO,QAAQ,IAAI,CAAC,OAAO,EAAE,GAAG,GAAG,eAAe,CAAC,EAAE,EAAE;AAErF,UAAM,mBAAmB,oBAAI,IAAqC;AAClE,eAAW,WAAW,aAAa;AACjC,YAAM,OAAO,iBAAiB,IAAI,QAAQ,gBAAgB,KAAK,CAAC;AAChE,WAAK,KAAK,OAAO;AACjB,uBAAiB,IAAI,QAAQ,kBAAkB,IAAI;AAAA,IACrD;AAEA,WAAO,QAAQ,IAAI,CAAC,WAAW;AAC7B,YAAM,WAAW,iBAAiB,IAAI,OAAO,EAAE;AAC/C,UAAI,CAAC,YAAY,SAAS,WAAW,EAAG,QAAO,EAAE,GAAG,QAAQ,eAAe,CAAC,EAAE;AAE9E,aAAO;AAAA,QACL,GAAG;AAAA,QACH,eAAe,qBAAqB,QAAQ;AAAA,MAC9C;AAAA,IACF,CAAC;AAAA,EACH;AACF;AAEO,MAAM,YAAgC,CAAC,yBAAyB;",
6
- "names": []
7
- }
@@ -1,63 +0,0 @@
1
- var __defProp = Object.defineProperty;
2
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
3
- var __decorateClass = (decorators, target, key, kind) => {
4
- var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
5
- for (var i = decorators.length - 1, decorator; i >= 0; i--)
6
- if (decorator = decorators[i])
7
- result = (kind ? decorator(target, key, result) : decorator(result)) || result;
8
- if (kind && result) __defProp(target, key, result);
9
- return result;
10
- };
11
- import { Entity, PrimaryKey, Property, Index } from "@mikro-orm/core";
12
- let SyncExternalIdMapping = class {
13
- constructor() {
14
- this.syncStatus = "not_synced";
15
- this.createdAt = /* @__PURE__ */ new Date();
16
- this.updatedAt = /* @__PURE__ */ new Date();
17
- }
18
- };
19
- __decorateClass([
20
- PrimaryKey({ type: "uuid", defaultRaw: "gen_random_uuid()" })
21
- ], SyncExternalIdMapping.prototype, "id", 2);
22
- __decorateClass([
23
- Property({ name: "integration_id", type: "text" })
24
- ], SyncExternalIdMapping.prototype, "integrationId", 2);
25
- __decorateClass([
26
- Property({ name: "internal_entity_type", type: "text" })
27
- ], SyncExternalIdMapping.prototype, "internalEntityType", 2);
28
- __decorateClass([
29
- Property({ name: "internal_entity_id", type: "uuid" })
30
- ], SyncExternalIdMapping.prototype, "internalEntityId", 2);
31
- __decorateClass([
32
- Property({ name: "external_id", type: "text" })
33
- ], SyncExternalIdMapping.prototype, "externalId", 2);
34
- __decorateClass([
35
- Property({ name: "sync_status", type: "text", default: "not_synced" })
36
- ], SyncExternalIdMapping.prototype, "syncStatus", 2);
37
- __decorateClass([
38
- Property({ name: "last_synced_at", type: Date, nullable: true })
39
- ], SyncExternalIdMapping.prototype, "lastSyncedAt", 2);
40
- __decorateClass([
41
- Property({ name: "organization_id", type: "uuid" })
42
- ], SyncExternalIdMapping.prototype, "organizationId", 2);
43
- __decorateClass([
44
- Property({ name: "tenant_id", type: "uuid" })
45
- ], SyncExternalIdMapping.prototype, "tenantId", 2);
46
- __decorateClass([
47
- Property({ name: "created_at", type: Date, onCreate: () => /* @__PURE__ */ new Date() })
48
- ], SyncExternalIdMapping.prototype, "createdAt", 2);
49
- __decorateClass([
50
- Property({ name: "updated_at", type: Date, onUpdate: () => /* @__PURE__ */ new Date() })
51
- ], SyncExternalIdMapping.prototype, "updatedAt", 2);
52
- __decorateClass([
53
- Property({ name: "deleted_at", type: Date, nullable: true })
54
- ], SyncExternalIdMapping.prototype, "deletedAt", 2);
55
- SyncExternalIdMapping = __decorateClass([
56
- Entity({ tableName: "sync_external_id_mappings" }),
57
- Index({ properties: ["internalEntityType", "internalEntityId", "organizationId"] }),
58
- Index({ properties: ["integrationId", "externalId", "organizationId"] })
59
- ], SyncExternalIdMapping);
60
- export {
61
- SyncExternalIdMapping
62
- };
63
- //# sourceMappingURL=entities.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/modules/integrations/data/entities.ts"],
4
- "sourcesContent": ["import { Entity, PrimaryKey, Property, Index } from '@mikro-orm/core'\n\n/**\n * Stores mappings between internal entity IDs and external system IDs.\n * Used by integration modules to track synced records across platforms.\n */\n@Entity({ tableName: 'sync_external_id_mappings' })\n@Index({ properties: ['internalEntityType', 'internalEntityId', 'organizationId'] })\n@Index({ properties: ['integrationId', 'externalId', 'organizationId'] })\nexport class SyncExternalIdMapping {\n @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })\n id!: string\n\n @Property({ name: 'integration_id', type: 'text' })\n integrationId!: string\n\n @Property({ name: 'internal_entity_type', type: 'text' })\n internalEntityType!: string\n\n @Property({ name: 'internal_entity_id', type: 'uuid' })\n internalEntityId!: string\n\n @Property({ name: 'external_id', type: 'text' })\n externalId!: string\n\n @Property({ name: 'sync_status', type: 'text', default: 'not_synced' })\n syncStatus: 'synced' | 'pending' | 'error' | 'not_synced' = 'not_synced'\n\n @Property({ name: 'last_synced_at', type: Date, nullable: true })\n lastSyncedAt?: Date | null\n\n @Property({ name: 'organization_id', type: 'uuid' })\n organizationId!: string\n\n @Property({ name: 'tenant_id', type: 'uuid' })\n tenantId!: string\n\n @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })\n createdAt: Date = new Date()\n\n @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })\n updatedAt: Date = new Date()\n\n @Property({ name: 'deleted_at', type: Date, nullable: true })\n deletedAt?: Date | null\n}\n"],
5
- "mappings": ";;;;;;;;;;AAAA,SAAS,QAAQ,YAAY,UAAU,aAAa;AAS7C,IAAM,wBAAN,MAA4B;AAAA,EAA5B;AAiBL,sBAA4D;AAY5D,qBAAkB,oBAAI,KAAK;AAG3B,qBAAkB,oBAAI,KAAK;AAAA;AAI7B;AAlCE;AAAA,EADC,WAAW,EAAE,MAAM,QAAQ,YAAY,oBAAoB,CAAC;AAAA,GADlD,sBAEX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,kBAAkB,MAAM,OAAO,CAAC;AAAA,GAJvC,sBAKX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,wBAAwB,MAAM,OAAO,CAAC;AAAA,GAP7C,sBAQX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,sBAAsB,MAAM,OAAO,CAAC;AAAA,GAV3C,sBAWX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,eAAe,MAAM,OAAO,CAAC;AAAA,GAbpC,sBAcX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,eAAe,MAAM,QAAQ,SAAS,aAAa,CAAC;AAAA,GAhB3D,sBAiBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,kBAAkB,MAAM,MAAM,UAAU,KAAK,CAAC;AAAA,GAnBrD,sBAoBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,mBAAmB,MAAM,OAAO,CAAC;AAAA,GAtBxC,sBAuBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,aAAa,MAAM,OAAO,CAAC;AAAA,GAzBlC,sBA0BX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,MAAM,oBAAI,KAAK,EAAE,CAAC;AAAA,GA5B7D,sBA6BX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,MAAM,oBAAI,KAAK,EAAE,CAAC;AAAA,GA/B7D,sBAgCX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,KAAK,CAAC;AAAA,GAlCjD,sBAmCX;AAnCW,wBAAN;AAAA,EAHN,OAAO,EAAE,WAAW,4BAA4B,CAAC;AAAA,EACjD,MAAM,EAAE,YAAY,CAAC,sBAAsB,oBAAoB,gBAAgB,EAAE,CAAC;AAAA,EAClF,MAAM,EAAE,YAAY,CAAC,iBAAiB,cAAc,gBAAgB,EAAE,CAAC;AAAA,GAC3D;",
6
- "names": []
7
- }
@@ -1,9 +0,0 @@
1
- const metadata = {
2
- id: "integrations",
3
- title: "Integrations",
4
- description: "Core integration framework \u2014 external ID mapping, status badges, and integration registry."
5
- };
6
- export {
7
- metadata
8
- };
9
- //# sourceMappingURL=index.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/modules/integrations/index.ts"],
4
- "sourcesContent": ["export const metadata = {\n id: 'integrations',\n title: 'Integrations',\n description: 'Core integration framework \u2014 external ID mapping, status badges, and integration registry.',\n}\n"],
5
- "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,aAAa;AACf;",
6
- "names": []
7
- }
@@ -1,13 +0,0 @@
1
- const setup = {
2
- defaultRoleFeatures: {
3
- superadmin: ["integrations.view", "integrations.manage"],
4
- admin: ["integrations.view", "integrations.manage"],
5
- employee: ["integrations.view"]
6
- }
7
- };
8
- var setup_default = setup;
9
- export {
10
- setup_default as default,
11
- setup
12
- };
13
- //# sourceMappingURL=setup.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/modules/integrations/setup.ts"],
4
- "sourcesContent": ["import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\n\nexport const setup: ModuleSetupConfig = {\n defaultRoleFeatures: {\n superadmin: ['integrations.view', 'integrations.manage'],\n admin: ['integrations.view', 'integrations.manage'],\n employee: ['integrations.view'],\n },\n}\n\nexport default setup\n"],
5
- "mappings": "AAEO,MAAM,QAA2B;AAAA,EACtC,qBAAqB;AAAA,IACnB,YAAY,CAAC,qBAAqB,qBAAqB;AAAA,IACvD,OAAO,CAAC,qBAAqB,qBAAqB;AAAA,IAClD,UAAU,CAAC,mBAAmB;AAAA,EAChC;AACF;AAEA,IAAO,gBAAQ;",
6
- "names": []
7
- }
@@ -1,69 +0,0 @@
1
- "use client";
2
- import { jsx, jsxs } from "react/jsx-runtime";
3
- import { getIntegrationTitle } from "@open-mercato/shared/modules/integrations/types";
4
- import { useT } from "@open-mercato/shared/lib/i18n/context";
5
- import { cn } from "@open-mercato/shared/lib/utils";
6
- const SYNC_STATUS_STYLES = {
7
- synced: { dot: "bg-green-500", label: "integrations.syncStatus.synced" },
8
- pending: { dot: "bg-yellow-500", label: "integrations.syncStatus.pending" },
9
- error: { dot: "bg-red-500", label: "integrations.syncStatus.error" },
10
- not_synced: { dot: "bg-gray-400", label: "integrations.syncStatus.notSynced" }
11
- };
12
- function SyncStatusBadge({ status, lastSynced }) {
13
- const t = useT();
14
- const config = SYNC_STATUS_STYLES[status];
15
- const label = t(config.label, status);
16
- return /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-xs text-muted-foreground", children: [
17
- /* @__PURE__ */ jsx("span", { className: cn("inline-block size-1.5 rounded-full", config.dot), "aria-hidden": "true" }),
18
- /* @__PURE__ */ jsx("span", { children: label }),
19
- lastSynced && /* @__PURE__ */ jsx("span", { title: lastSynced, children: new Date(lastSynced).toLocaleDateString() })
20
- ] });
21
- }
22
- function ExternalLinkIcon() {
23
- return /* @__PURE__ */ jsxs("svg", { className: "size-3.5", viewBox: "0 0 16 16", fill: "none", stroke: "currentColor", strokeWidth: "1.5", children: [
24
- /* @__PURE__ */ jsx("path", { d: "M6.5 3.5H3a1 1 0 0 0-1 1V13a1 1 0 0 0 1 1h8.5a1 1 0 0 0 1-1V9.5" }),
25
- /* @__PURE__ */ jsx("path", { d: "M9.5 2h4.5v4.5M14 2 7.5 8.5" })
26
- ] });
27
- }
28
- function ExternalIdsWidget({ data }) {
29
- const t = useT();
30
- const integrations = data?._integrations;
31
- if (!integrations || Object.keys(integrations).length === 0) return null;
32
- return /* @__PURE__ */ jsxs("div", { className: "rounded-lg border bg-card p-4", children: [
33
- /* @__PURE__ */ jsx("h3", { className: "mb-3 text-sm font-medium", children: t("integrations.externalIds.title", "External IDs") }),
34
- /* @__PURE__ */ jsx("div", { className: "space-y-2", children: Object.entries(integrations).map(([integrationId, mapping]) => /* @__PURE__ */ jsxs(
35
- "div",
36
- {
37
- className: "flex items-center justify-between gap-2 rounded-md bg-muted/50 px-3 py-2",
38
- children: [
39
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
40
- /* @__PURE__ */ jsx("span", { className: "text-sm font-medium truncate", children: getIntegrationTitle(integrationId) }),
41
- /* @__PURE__ */ jsx("code", { className: "rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-muted-foreground", children: mapping.externalId }),
42
- mapping.externalUrl && /* @__PURE__ */ jsx(
43
- "a",
44
- {
45
- href: mapping.externalUrl,
46
- target: "_blank",
47
- rel: "noopener noreferrer",
48
- className: "text-muted-foreground hover:text-foreground transition-colors",
49
- "aria-label": t("integrations.externalIds.openExternal", "Open in external system"),
50
- children: /* @__PURE__ */ jsx(ExternalLinkIcon, {})
51
- }
52
- )
53
- ] }),
54
- /* @__PURE__ */ jsx(SyncStatusBadge, { status: mapping.syncStatus, lastSynced: mapping.lastSyncedAt })
55
- ]
56
- },
57
- integrationId
58
- )) })
59
- ] });
60
- }
61
- ExternalIdsWidget.metadata = {
62
- id: "integrations.injection.external-ids",
63
- title: "External IDs",
64
- features: ["integrations.view"]
65
- };
66
- export {
67
- ExternalIdsWidget as default
68
- };
69
- //# sourceMappingURL=widget.client.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../../../src/modules/integrations/widgets/injection/external-ids/widget.client.tsx"],
4
- "sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport type { InjectionWidgetComponentProps } from '@open-mercato/shared/modules/widgets/injection'\nimport type { ExternalIdMapping } from '@open-mercato/shared/modules/integrations/types'\nimport { getIntegrationTitle } from '@open-mercato/shared/modules/integrations/types'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { cn } from '@open-mercato/shared/lib/utils'\n\ntype IntegrationsData = Record<string, ExternalIdMapping>\n\nconst SYNC_STATUS_STYLES: Record<ExternalIdMapping['syncStatus'], { dot: string; label: string }> = {\n synced: { dot: 'bg-green-500', label: 'integrations.syncStatus.synced' },\n pending: { dot: 'bg-yellow-500', label: 'integrations.syncStatus.pending' },\n error: { dot: 'bg-red-500', label: 'integrations.syncStatus.error' },\n not_synced: { dot: 'bg-gray-400', label: 'integrations.syncStatus.notSynced' },\n}\n\nfunction SyncStatusBadge({ status, lastSynced }: { status: ExternalIdMapping['syncStatus']; lastSynced?: string }) {\n const t = useT()\n const config = SYNC_STATUS_STYLES[status]\n const label = t(config.label, status)\n\n return (\n <span className=\"inline-flex items-center gap-1 text-xs text-muted-foreground\">\n <span className={cn('inline-block size-1.5 rounded-full', config.dot)} aria-hidden=\"true\" />\n <span>{label}</span>\n {lastSynced && (\n <span title={lastSynced}>\n {new Date(lastSynced).toLocaleDateString()}\n </span>\n )}\n </span>\n )\n}\n\nfunction ExternalLinkIcon() {\n return (\n <svg className=\"size-3.5\" viewBox=\"0 0 16 16\" fill=\"none\" stroke=\"currentColor\" strokeWidth=\"1.5\">\n <path d=\"M6.5 3.5H3a1 1 0 0 0-1 1V13a1 1 0 0 0 1 1h8.5a1 1 0 0 0 1-1V9.5\" />\n <path d=\"M9.5 2h4.5v4.5M14 2 7.5 8.5\" />\n </svg>\n )\n}\n\nexport default function ExternalIdsWidget({ data }: InjectionWidgetComponentProps) {\n const t = useT()\n const integrations = (data as Record<string, unknown>)?._integrations as IntegrationsData | undefined\n\n if (!integrations || Object.keys(integrations).length === 0) return null\n\n return (\n <div className=\"rounded-lg border bg-card p-4\">\n <h3 className=\"mb-3 text-sm font-medium\">\n {t('integrations.externalIds.title', 'External IDs')}\n </h3>\n <div className=\"space-y-2\">\n {Object.entries(integrations).map(([integrationId, mapping]) => (\n <div\n key={integrationId}\n className=\"flex items-center justify-between gap-2 rounded-md bg-muted/50 px-3 py-2\"\n >\n <div className=\"flex items-center gap-2 min-w-0\">\n <span className=\"text-sm font-medium truncate\">\n {getIntegrationTitle(integrationId)}\n </span>\n <code className=\"rounded bg-muted px-1.5 py-0.5 text-xs font-mono text-muted-foreground\">\n {mapping.externalId}\n </code>\n {mapping.externalUrl && (\n <a\n href={mapping.externalUrl}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n className=\"text-muted-foreground hover:text-foreground transition-colors\"\n aria-label={t('integrations.externalIds.openExternal', 'Open in external system')}\n >\n <ExternalLinkIcon />\n </a>\n )}\n </div>\n <SyncStatusBadge status={mapping.syncStatus} lastSynced={mapping.lastSyncedAt} />\n </div>\n ))}\n </div>\n </div>\n )\n}\n\nExternalIdsWidget.metadata = {\n id: 'integrations.injection.external-ids',\n title: 'External IDs',\n features: ['integrations.view'],\n}\n"],
5
- "mappings": ";AAwBI,SACE,KADF;AAnBJ,SAAS,2BAA2B;AACpC,SAAS,YAAY;AACrB,SAAS,UAAU;AAInB,MAAM,qBAA8F;AAAA,EAClG,QAAQ,EAAE,KAAK,gBAAgB,OAAO,iCAAiC;AAAA,EACvE,SAAS,EAAE,KAAK,iBAAiB,OAAO,kCAAkC;AAAA,EAC1E,OAAO,EAAE,KAAK,cAAc,OAAO,gCAAgC;AAAA,EACnE,YAAY,EAAE,KAAK,eAAe,OAAO,oCAAoC;AAC/E;AAEA,SAAS,gBAAgB,EAAE,QAAQ,WAAW,GAAqE;AACjH,QAAM,IAAI,KAAK;AACf,QAAM,SAAS,mBAAmB,MAAM;AACxC,QAAM,QAAQ,EAAE,OAAO,OAAO,MAAM;AAEpC,SACE,qBAAC,UAAK,WAAU,gEACd;AAAA,wBAAC,UAAK,WAAW,GAAG,sCAAsC,OAAO,GAAG,GAAG,eAAY,QAAO;AAAA,IAC1F,oBAAC,UAAM,iBAAM;AAAA,IACZ,cACC,oBAAC,UAAK,OAAO,YACV,cAAI,KAAK,UAAU,EAAE,mBAAmB,GAC3C;AAAA,KAEJ;AAEJ;AAEA,SAAS,mBAAmB;AAC1B,SACE,qBAAC,SAAI,WAAU,YAAW,SAAQ,aAAY,MAAK,QAAO,QAAO,gBAAe,aAAY,OAC1F;AAAA,wBAAC,UAAK,GAAE,mEAAkE;AAAA,IAC1E,oBAAC,UAAK,GAAE,+BAA8B;AAAA,KACxC;AAEJ;AAEe,SAAR,kBAAmC,EAAE,KAAK,GAAkC;AACjF,QAAM,IAAI,KAAK;AACf,QAAM,eAAgB,MAAkC;AAExD,MAAI,CAAC,gBAAgB,OAAO,KAAK,YAAY,EAAE,WAAW,EAAG,QAAO;AAEpE,SACE,qBAAC,SAAI,WAAU,iCACb;AAAA,wBAAC,QAAG,WAAU,4BACX,YAAE,kCAAkC,cAAc,GACrD;AAAA,IACA,oBAAC,SAAI,WAAU,aACZ,iBAAO,QAAQ,YAAY,EAAE,IAAI,CAAC,CAAC,eAAe,OAAO,MACxD;AAAA,MAAC;AAAA;AAAA,QAEC,WAAU;AAAA,QAEV;AAAA,+BAAC,SAAI,WAAU,mCACb;AAAA,gCAAC,UAAK,WAAU,gCACb,8BAAoB,aAAa,GACpC;AAAA,YACA,oBAAC,UAAK,WAAU,0EACb,kBAAQ,YACX;AAAA,YACC,QAAQ,eACP;AAAA,cAAC;AAAA;AAAA,gBACC,MAAM,QAAQ;AAAA,gBACd,QAAO;AAAA,gBACP,KAAI;AAAA,gBACJ,WAAU;AAAA,gBACV,cAAY,EAAE,yCAAyC,yBAAyB;AAAA,gBAEhF,8BAAC,oBAAiB;AAAA;AAAA,YACpB;AAAA,aAEJ;AAAA,UACA,oBAAC,mBAAgB,QAAQ,QAAQ,YAAY,YAAY,QAAQ,cAAc;AAAA;AAAA;AAAA,MAtB1E;AAAA,IAuBP,CACD,GACH;AAAA,KACF;AAEJ;AAEA,kBAAkB,WAAW;AAAA,EAC3B,IAAI;AAAA,EACJ,OAAO;AAAA,EACP,UAAU,CAAC,mBAAmB;AAChC;",
6
- "names": []
7
- }
@@ -1,13 +0,0 @@
1
- const injectionTable = {
2
- // External IDs widget appears in detail page sidebars for all entities
3
- "detail:*:sidebar": {
4
- widgetId: "integrations.injection.external-ids",
5
- priority: -10
6
- }
7
- };
8
- var injection_table_default = injectionTable;
9
- export {
10
- injection_table_default as default,
11
- injectionTable
12
- };
13
- //# sourceMappingURL=injection-table.js.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../../src/modules/integrations/widgets/injection-table.ts"],
4
- "sourcesContent": ["import type { ModuleInjectionTable } from '@open-mercato/shared/modules/widgets/injection'\n\n/**\n * Integrations module injection table.\n *\n * The external-ids widget auto-appears on entity detail pages via wildcard spot matching.\n * Status badge widgets are registered by individual integration modules (e.g. sync_medusa).\n */\nexport const injectionTable: ModuleInjectionTable = {\n // External IDs widget appears in detail page sidebars for all entities\n 'detail:*:sidebar': {\n widgetId: 'integrations.injection.external-ids',\n priority: -10,\n },\n}\n\nexport default injectionTable\n"],
5
- "mappings": "AAQO,MAAM,iBAAuC;AAAA;AAAA,EAElD,oBAAoB;AAAA,IAClB,UAAU;AAAA,IACV,UAAU;AAAA,EACZ;AACF;AAEA,IAAO,0BAAQ;",
6
- "names": []
7
- }
@@ -1,4 +0,0 @@
1
- export const features = [
2
- { id: 'integrations.view', title: 'View integrations and external ID mappings', module: 'integrations' },
3
- { id: 'integrations.manage', title: 'Manage integration configurations', module: 'integrations' },
4
- ]
@@ -1,98 +0,0 @@
1
- /**
2
- * External ID Mapping Enricher
3
- *
4
- * Enriches any entity's API response with external integration ID mappings.
5
- * Adds `_integrations` namespace containing all external IDs for the record.
6
- *
7
- * Uses batch queries via `enrichMany` to prevent N+1.
8
- */
9
-
10
- import type { ResponseEnricher, EnricherContext } from '@open-mercato/shared/lib/crud/response-enricher'
11
- import type { ExternalIdEnrichment } from '@open-mercato/shared/modules/integrations/types'
12
- import { getIntegration } from '@open-mercato/shared/modules/integrations/types'
13
- import { SyncExternalIdMapping } from './entities'
14
-
15
- type EntityRecord = Record<string, unknown> & { id: string }
16
-
17
- function buildIntegrationData(
18
- mappings: SyncExternalIdMapping[],
19
- ): ExternalIdEnrichment['_integrations'] {
20
- const data: ExternalIdEnrichment['_integrations'] = {}
21
-
22
- for (const mapping of mappings) {
23
- const definition = getIntegration(mapping.integrationId)
24
- data[mapping.integrationId] = {
25
- externalId: mapping.externalId,
26
- externalUrl: definition?.buildExternalUrl?.(mapping.externalId),
27
- lastSyncedAt: mapping.lastSyncedAt?.toISOString(),
28
- syncStatus: mapping.syncStatus,
29
- }
30
- }
31
-
32
- return data
33
- }
34
-
35
- const externalIdMappingEnricher: ResponseEnricher<EntityRecord, ExternalIdEnrichment> = {
36
- id: 'integrations.external-id-mapping',
37
- targetEntity: '*',
38
- features: ['integrations.view'],
39
- priority: 10,
40
- timeout: 500,
41
- critical: false,
42
- fallback: {},
43
-
44
- async enrichOne(record, context: EnricherContext & { targetEntity?: string }) {
45
- const em = (context.em as any).fork()
46
- const targetEntity = (context as any).targetEntity as string | undefined
47
- if (!targetEntity) return { ...record, _integrations: {} }
48
-
49
- const mappings: SyncExternalIdMapping[] = await em.find(SyncExternalIdMapping, {
50
- internalEntityType: targetEntity,
51
- internalEntityId: record.id,
52
- organizationId: context.organizationId,
53
- deletedAt: null,
54
- })
55
-
56
- if (mappings.length === 0) return { ...record, _integrations: {} }
57
-
58
- return {
59
- ...record,
60
- _integrations: buildIntegrationData(mappings),
61
- }
62
- },
63
-
64
- async enrichMany(records, context: EnricherContext & { targetEntity?: string }) {
65
- const em = (context.em as any).fork()
66
- const targetEntity = (context as any).targetEntity as string | undefined
67
- if (!targetEntity || records.length === 0) return records.map((r) => ({ ...r, _integrations: {} }))
68
-
69
- const recordIds = records.map((r) => r.id)
70
- const allMappings: SyncExternalIdMapping[] = await em.find(SyncExternalIdMapping, {
71
- internalEntityType: targetEntity,
72
- internalEntityId: { $in: recordIds },
73
- organizationId: context.organizationId,
74
- deletedAt: null,
75
- })
76
-
77
- if (allMappings.length === 0) return records.map((r) => ({ ...r, _integrations: {} }))
78
-
79
- const mappingsByRecord = new Map<string, SyncExternalIdMapping[]>()
80
- for (const mapping of allMappings) {
81
- const list = mappingsByRecord.get(mapping.internalEntityId) ?? []
82
- list.push(mapping)
83
- mappingsByRecord.set(mapping.internalEntityId, list)
84
- }
85
-
86
- return records.map((record) => {
87
- const mappings = mappingsByRecord.get(record.id)
88
- if (!mappings || mappings.length === 0) return { ...record, _integrations: {} }
89
-
90
- return {
91
- ...record,
92
- _integrations: buildIntegrationData(mappings),
93
- }
94
- })
95
- },
96
- }
97
-
98
- export const enrichers: ResponseEnricher[] = [externalIdMappingEnricher]
@@ -1,46 +0,0 @@
1
- import { Entity, PrimaryKey, Property, Index } from '@mikro-orm/core'
2
-
3
- /**
4
- * Stores mappings between internal entity IDs and external system IDs.
5
- * Used by integration modules to track synced records across platforms.
6
- */
7
- @Entity({ tableName: 'sync_external_id_mappings' })
8
- @Index({ properties: ['internalEntityType', 'internalEntityId', 'organizationId'] })
9
- @Index({ properties: ['integrationId', 'externalId', 'organizationId'] })
10
- export class SyncExternalIdMapping {
11
- @PrimaryKey({ type: 'uuid', defaultRaw: 'gen_random_uuid()' })
12
- id!: string
13
-
14
- @Property({ name: 'integration_id', type: 'text' })
15
- integrationId!: string
16
-
17
- @Property({ name: 'internal_entity_type', type: 'text' })
18
- internalEntityType!: string
19
-
20
- @Property({ name: 'internal_entity_id', type: 'uuid' })
21
- internalEntityId!: string
22
-
23
- @Property({ name: 'external_id', type: 'text' })
24
- externalId!: string
25
-
26
- @Property({ name: 'sync_status', type: 'text', default: 'not_synced' })
27
- syncStatus: 'synced' | 'pending' | 'error' | 'not_synced' = 'not_synced'
28
-
29
- @Property({ name: 'last_synced_at', type: Date, nullable: true })
30
- lastSyncedAt?: Date | null
31
-
32
- @Property({ name: 'organization_id', type: 'uuid' })
33
- organizationId!: string
34
-
35
- @Property({ name: 'tenant_id', type: 'uuid' })
36
- tenantId!: string
37
-
38
- @Property({ name: 'created_at', type: Date, onCreate: () => new Date() })
39
- createdAt: Date = new Date()
40
-
41
- @Property({ name: 'updated_at', type: Date, onUpdate: () => new Date() })
42
- updatedAt: Date = new Date()
43
-
44
- @Property({ name: 'deleted_at', type: Date, nullable: true })
45
- deletedAt?: Date | null
46
- }
@@ -1,5 +0,0 @@
1
- export const metadata = {
2
- id: 'integrations',
3
- title: 'Integrations',
4
- description: 'Core integration framework — external ID mapping, status badges, and integration registry.',
5
- }
@@ -1,11 +0,0 @@
1
- import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'
2
-
3
- export const setup: ModuleSetupConfig = {
4
- defaultRoleFeatures: {
5
- superadmin: ['integrations.view', 'integrations.manage'],
6
- admin: ['integrations.view', 'integrations.manage'],
7
- employee: ['integrations.view'],
8
- },
9
- }
10
-
11
- export default setup