@open-mercato/core 0.4.6-develop-a88276bc52 → 0.4.6-develop-806a2ed6b9

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 (226) hide show
  1. package/AGENTS.md +10 -0
  2. package/dist/generated/entities/integration_credentials/index.js +19 -0
  3. package/dist/generated/entities/integration_credentials/index.js.map +7 -0
  4. package/dist/generated/entities/integration_log/index.js +27 -0
  5. package/dist/generated/entities/integration_log/index.js.map +7 -0
  6. package/dist/generated/entities/integration_state/index.js +27 -0
  7. package/dist/generated/entities/integration_state/index.js.map +7 -0
  8. package/dist/generated/entities/sync_cursor/index.js +19 -0
  9. package/dist/generated/entities/sync_cursor/index.js.map +7 -0
  10. package/dist/generated/entities/sync_external_id_mapping/index.js +27 -0
  11. package/dist/generated/entities/sync_external_id_mapping/index.js.map +7 -0
  12. package/dist/generated/entities/sync_mapping/index.js +19 -0
  13. package/dist/generated/entities/sync_mapping/index.js.map +7 -0
  14. package/dist/generated/entities/sync_run/index.js +45 -0
  15. package/dist/generated/entities/sync_run/index.js.map +7 -0
  16. package/dist/generated/entities/sync_schedule/index.js +35 -0
  17. package/dist/generated/entities/sync_schedule/index.js.map +7 -0
  18. package/dist/generated/entities.ids.generated.js +14 -0
  19. package/dist/generated/entities.ids.generated.js.map +2 -2
  20. package/dist/generated/entity-fields-registry.js +16 -0
  21. package/dist/generated/entity-fields-registry.js.map +2 -2
  22. package/dist/modules/data_sync/acl.js +11 -0
  23. package/dist/modules/data_sync/acl.js.map +7 -0
  24. package/dist/modules/data_sync/api/mappings/[id]/route.js +137 -0
  25. package/dist/modules/data_sync/api/mappings/[id]/route.js.map +7 -0
  26. package/dist/modules/data_sync/api/mappings/route.js +132 -0
  27. package/dist/modules/data_sync/api/mappings/route.js.map +7 -0
  28. package/dist/modules/data_sync/api/run.js +87 -0
  29. package/dist/modules/data_sync/api/run.js.map +7 -0
  30. package/dist/modules/data_sync/api/runs/[id]/cancel.js +49 -0
  31. package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +7 -0
  32. package/dist/modules/data_sync/api/runs/[id]/retry.js +93 -0
  33. package/dist/modules/data_sync/api/runs/[id]/retry.js.map +7 -0
  34. package/dist/modules/data_sync/api/runs/[id]/route.js +69 -0
  35. package/dist/modules/data_sync/api/runs/[id]/route.js.map +7 -0
  36. package/dist/modules/data_sync/api/runs.js +66 -0
  37. package/dist/modules/data_sync/api/runs.js.map +7 -0
  38. package/dist/modules/data_sync/api/validate.js +66 -0
  39. package/dist/modules/data_sync/api/validate.js.map +7 -0
  40. package/dist/modules/data_sync/backend/data-sync/page.js +216 -0
  41. package/dist/modules/data_sync/backend/data-sync/page.js.map +7 -0
  42. package/dist/modules/data_sync/backend/data-sync/page.meta.js +25 -0
  43. package/dist/modules/data_sync/backend/data-sync/page.meta.js.map +7 -0
  44. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js +178 -0
  45. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js.map +7 -0
  46. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.meta.js +14 -0
  47. package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.meta.js.map +7 -0
  48. package/dist/modules/data_sync/data/entities.js +228 -0
  49. package/dist/modules/data_sync/data/entities.js.map +7 -0
  50. package/dist/modules/data_sync/data/validators.js +32 -0
  51. package/dist/modules/data_sync/data/validators.js.map +7 -0
  52. package/dist/modules/data_sync/di.js +26 -0
  53. package/dist/modules/data_sync/di.js.map +7 -0
  54. package/dist/modules/data_sync/events.js +16 -0
  55. package/dist/modules/data_sync/events.js.map +7 -0
  56. package/dist/modules/data_sync/index.js +9 -0
  57. package/dist/modules/data_sync/index.js.map +7 -0
  58. package/dist/modules/data_sync/lib/adapter-registry.js +16 -0
  59. package/dist/modules/data_sync/lib/adapter-registry.js.map +7 -0
  60. package/dist/modules/data_sync/lib/adapter.js +1 -0
  61. package/dist/modules/data_sync/lib/adapter.js.map +7 -0
  62. package/dist/modules/data_sync/lib/id-mapping.js +79 -0
  63. package/dist/modules/data_sync/lib/id-mapping.js.map +7 -0
  64. package/dist/modules/data_sync/lib/queue.js +17 -0
  65. package/dist/modules/data_sync/lib/queue.js.map +7 -0
  66. package/dist/modules/data_sync/lib/sync-engine.js +309 -0
  67. package/dist/modules/data_sync/lib/sync-engine.js.map +7 -0
  68. package/dist/modules/data_sync/lib/sync-run-service.js +148 -0
  69. package/dist/modules/data_sync/lib/sync-run-service.js.map +7 -0
  70. package/dist/modules/data_sync/migrations/Migration20260304113737.js +17 -0
  71. package/dist/modules/data_sync/migrations/Migration20260304113737.js.map +7 -0
  72. package/dist/modules/data_sync/setup.js +13 -0
  73. package/dist/modules/data_sync/setup.js.map +7 -0
  74. package/dist/modules/data_sync/workers/sync-export.js +14 -0
  75. package/dist/modules/data_sync/workers/sync-export.js.map +7 -0
  76. package/dist/modules/data_sync/workers/sync-import.js +14 -0
  77. package/dist/modules/data_sync/workers/sync-import.js.map +7 -0
  78. package/dist/modules/data_sync/workers/sync-scheduled.js +63 -0
  79. package/dist/modules/data_sync/workers/sync-scheduled.js.map +7 -0
  80. package/dist/modules/entities/lib/encryptionDefaults.js +4 -0
  81. package/dist/modules/entities/lib/encryptionDefaults.js.map +2 -2
  82. package/dist/modules/integrations/acl.js +4 -1
  83. package/dist/modules/integrations/acl.js.map +2 -2
  84. package/dist/modules/integrations/api/[id]/credentials/route.js +127 -0
  85. package/dist/modules/integrations/api/[id]/credentials/route.js.map +7 -0
  86. package/dist/modules/integrations/api/[id]/health/route.js +46 -0
  87. package/dist/modules/integrations/api/[id]/health/route.js.map +7 -0
  88. package/dist/modules/integrations/api/[id]/route.js +65 -0
  89. package/dist/modules/integrations/api/[id]/route.js.map +7 -0
  90. package/dist/modules/integrations/api/[id]/state/route.js +109 -0
  91. package/dist/modules/integrations/api/[id]/state/route.js.map +7 -0
  92. package/dist/modules/integrations/api/[id]/version/route.js +117 -0
  93. package/dist/modules/integrations/api/[id]/version/route.js.map +7 -0
  94. package/dist/modules/integrations/api/guards.js +31 -0
  95. package/dist/modules/integrations/api/guards.js.map +7 -0
  96. package/dist/modules/integrations/api/logs/route.js +60 -0
  97. package/dist/modules/integrations/api/logs/route.js.map +7 -0
  98. package/dist/modules/integrations/api/openapi.js +25 -0
  99. package/dist/modules/integrations/api/openapi.js.map +7 -0
  100. package/dist/modules/integrations/api/route.js +68 -0
  101. package/dist/modules/integrations/api/route.js.map +7 -0
  102. package/dist/modules/integrations/backend/integrations/[id]/page.js +313 -0
  103. package/dist/modules/integrations/backend/integrations/[id]/page.js.map +7 -0
  104. package/dist/modules/integrations/backend/integrations/[id]/page.meta.js +15 -0
  105. package/dist/modules/integrations/backend/integrations/[id]/page.meta.js.map +7 -0
  106. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +189 -0
  107. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +7 -0
  108. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.meta.js +15 -0
  109. package/dist/modules/integrations/backend/integrations/bundle/[id]/page.meta.js.map +7 -0
  110. package/dist/modules/integrations/backend/integrations/page.js +212 -0
  111. package/dist/modules/integrations/backend/integrations/page.js.map +7 -0
  112. package/dist/modules/integrations/backend/integrations/page.meta.js +22 -0
  113. package/dist/modules/integrations/backend/integrations/page.meta.js.map +7 -0
  114. package/dist/modules/integrations/data/enrichers.js +27 -12
  115. package/dist/modules/integrations/data/enrichers.js.map +2 -2
  116. package/dist/modules/integrations/data/entities.js +136 -1
  117. package/dist/modules/integrations/data/entities.js.map +2 -2
  118. package/dist/modules/integrations/data/validators.js +36 -0
  119. package/dist/modules/integrations/data/validators.js.map +7 -0
  120. package/dist/modules/integrations/di.js +24 -0
  121. package/dist/modules/integrations/di.js.map +7 -0
  122. package/dist/modules/integrations/events.js +19 -0
  123. package/dist/modules/integrations/events.js.map +7 -0
  124. package/dist/modules/integrations/lib/credentials-service.js +159 -0
  125. package/dist/modules/integrations/lib/credentials-service.js.map +7 -0
  126. package/dist/modules/integrations/lib/health-service.js +37 -0
  127. package/dist/modules/integrations/lib/health-service.js.map +7 -0
  128. package/dist/modules/integrations/lib/log-service.js +66 -0
  129. package/dist/modules/integrations/lib/log-service.js.map +7 -0
  130. package/dist/modules/integrations/lib/registry-service.js +33 -0
  131. package/dist/modules/integrations/lib/registry-service.js.map +7 -0
  132. package/dist/modules/integrations/lib/state-service.js +55 -0
  133. package/dist/modules/integrations/lib/state-service.js.map +7 -0
  134. package/dist/modules/integrations/lib/types.js +1 -0
  135. package/dist/modules/integrations/lib/types.js.map +7 -0
  136. package/dist/modules/integrations/migrations/Migration20260304113737.js +19 -0
  137. package/dist/modules/integrations/migrations/Migration20260304113737.js.map +7 -0
  138. package/dist/modules/integrations/setup.js +2 -2
  139. package/dist/modules/integrations/setup.js.map +2 -2
  140. package/dist/modules/integrations/widgets/injection-table.js.map +1 -1
  141. package/dist/modules/integrations/workers/log-pruner.js +18 -0
  142. package/dist/modules/integrations/workers/log-pruner.js.map +7 -0
  143. package/generated/entities/integration_credentials/index.ts +8 -0
  144. package/generated/entities/integration_log/index.ts +12 -0
  145. package/generated/entities/integration_state/index.ts +12 -0
  146. package/generated/entities/sync_cursor/index.ts +8 -0
  147. package/generated/entities/sync_external_id_mapping/index.ts +12 -0
  148. package/generated/entities/sync_mapping/index.ts +8 -0
  149. package/generated/entities/sync_run/index.ts +21 -0
  150. package/generated/entities/sync_schedule/index.ts +16 -0
  151. package/generated/entities.ids.generated.ts +14 -0
  152. package/generated/entity-fields-registry.ts +16 -0
  153. package/package.json +2 -2
  154. package/src/modules/data_sync/AGENTS.md +157 -0
  155. package/src/modules/data_sync/acl.ts +7 -0
  156. package/src/modules/data_sync/api/mappings/[id]/route.ts +158 -0
  157. package/src/modules/data_sync/api/mappings/route.ts +144 -0
  158. package/src/modules/data_sync/api/run.ts +97 -0
  159. package/src/modules/data_sync/api/runs/[id]/cancel.ts +57 -0
  160. package/src/modules/data_sync/api/runs/[id]/retry.ts +108 -0
  161. package/src/modules/data_sync/api/runs/[id]/route.ts +81 -0
  162. package/src/modules/data_sync/api/runs.ts +69 -0
  163. package/src/modules/data_sync/api/validate.ts +73 -0
  164. package/src/modules/data_sync/backend/data-sync/page.meta.ts +21 -0
  165. package/src/modules/data_sync/backend/data-sync/page.tsx +244 -0
  166. package/src/modules/data_sync/backend/data-sync/runs/[id]/page.meta.ts +10 -0
  167. package/src/modules/data_sync/backend/data-sync/runs/[id]/page.tsx +278 -0
  168. package/src/modules/data_sync/data/entities.ts +180 -0
  169. package/src/modules/data_sync/data/validators.ts +35 -0
  170. package/src/modules/data_sync/di.ts +38 -0
  171. package/src/modules/data_sync/events.ts +12 -0
  172. package/src/modules/data_sync/i18n/de.json +48 -0
  173. package/src/modules/data_sync/i18n/en.json +48 -0
  174. package/src/modules/data_sync/i18n/es.json +48 -0
  175. package/src/modules/data_sync/i18n/pl.json +48 -0
  176. package/src/modules/data_sync/index.ts +5 -0
  177. package/src/modules/data_sync/lib/adapter-registry.ts +15 -0
  178. package/src/modules/data_sync/lib/adapter.ts +90 -0
  179. package/src/modules/data_sync/lib/id-mapping.ts +95 -0
  180. package/src/modules/data_sync/lib/queue.ts +19 -0
  181. package/src/modules/data_sync/lib/sync-engine.ts +375 -0
  182. package/src/modules/data_sync/lib/sync-run-service.ts +187 -0
  183. package/src/modules/data_sync/migrations/.snapshot-open-mercato.json +653 -0
  184. package/src/modules/data_sync/migrations/Migration20260304113737.ts +19 -0
  185. package/src/modules/data_sync/setup.ts +11 -0
  186. package/src/modules/data_sync/workers/sync-export.ts +27 -0
  187. package/src/modules/data_sync/workers/sync-import.ts +27 -0
  188. package/src/modules/data_sync/workers/sync-scheduled.ts +84 -0
  189. package/src/modules/entities/lib/encryptionDefaults.ts +4 -0
  190. package/src/modules/integrations/AGENTS.md +160 -0
  191. package/src/modules/integrations/acl.ts +3 -0
  192. package/src/modules/integrations/api/[id]/credentials/route.ts +142 -0
  193. package/src/modules/integrations/api/[id]/health/route.ts +53 -0
  194. package/src/modules/integrations/api/[id]/route.ts +76 -0
  195. package/src/modules/integrations/api/[id]/state/route.ts +121 -0
  196. package/src/modules/integrations/api/[id]/version/route.ts +132 -0
  197. package/src/modules/integrations/api/guards.ts +59 -0
  198. package/src/modules/integrations/api/logs/route.ts +63 -0
  199. package/src/modules/integrations/api/openapi.ts +22 -0
  200. package/src/modules/integrations/api/route.ts +73 -0
  201. package/src/modules/integrations/backend/integrations/[id]/page.meta.ts +11 -0
  202. package/src/modules/integrations/backend/integrations/[id]/page.tsx +424 -0
  203. package/src/modules/integrations/backend/integrations/bundle/[id]/page.meta.ts +11 -0
  204. package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +249 -0
  205. package/src/modules/integrations/backend/integrations/page.meta.ts +18 -0
  206. package/src/modules/integrations/backend/integrations/page.tsx +296 -0
  207. package/src/modules/integrations/data/enrichers.ts +35 -18
  208. package/src/modules/integrations/data/entities.ts +114 -5
  209. package/src/modules/integrations/data/validators.ts +41 -0
  210. package/src/modules/integrations/di.ts +31 -0
  211. package/src/modules/integrations/events.ts +17 -0
  212. package/src/modules/integrations/i18n/de.json +70 -0
  213. package/src/modules/integrations/i18n/en.json +70 -0
  214. package/src/modules/integrations/i18n/es.json +70 -0
  215. package/src/modules/integrations/i18n/pl.json +70 -0
  216. package/src/modules/integrations/lib/credentials-service.ts +204 -0
  217. package/src/modules/integrations/lib/health-service.ts +59 -0
  218. package/src/modules/integrations/lib/log-service.ts +84 -0
  219. package/src/modules/integrations/lib/registry-service.ts +42 -0
  220. package/src/modules/integrations/lib/state-service.ts +64 -0
  221. package/src/modules/integrations/lib/types.ts +4 -0
  222. package/src/modules/integrations/migrations/.snapshot-open-mercato.json +582 -0
  223. package/src/modules/integrations/migrations/Migration20260304113737.ts +21 -0
  224. package/src/modules/integrations/setup.ts +2 -2
  225. package/src/modules/integrations/widgets/injection-table.ts +1 -1
  226. package/src/modules/integrations/workers/log-pruner.ts +30 -0
@@ -0,0 +1,148 @@
1
+ import { findAndCountWithDecryption, findOneWithDecryption, findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
2
+ import { SyncCursor, SyncRun } from "../data/entities.js";
3
+ function createSyncRunService(em) {
4
+ return {
5
+ async createRun(input, scope) {
6
+ const row = em.create(SyncRun, {
7
+ integrationId: input.integrationId,
8
+ entityType: input.entityType,
9
+ direction: input.direction,
10
+ status: "pending",
11
+ cursor: input.cursor,
12
+ initialCursor: input.cursor,
13
+ triggeredBy: input.triggeredBy,
14
+ progressJobId: input.progressJobId,
15
+ jobId: input.jobId,
16
+ organizationId: scope.organizationId,
17
+ tenantId: scope.tenantId
18
+ });
19
+ await em.persistAndFlush(row);
20
+ return row;
21
+ },
22
+ async getRun(runId, scope) {
23
+ return findOneWithDecryption(
24
+ em,
25
+ SyncRun,
26
+ {
27
+ id: runId,
28
+ organizationId: scope.organizationId,
29
+ tenantId: scope.tenantId,
30
+ deletedAt: null
31
+ },
32
+ void 0,
33
+ scope
34
+ );
35
+ },
36
+ async listRuns(query, scope) {
37
+ const where = {
38
+ organizationId: scope.organizationId,
39
+ tenantId: scope.tenantId,
40
+ deletedAt: null
41
+ };
42
+ if (query.integrationId) where.integrationId = query.integrationId;
43
+ if (query.entityType) where.entityType = query.entityType;
44
+ if (query.direction) where.direction = query.direction;
45
+ if (query.status) where.status = query.status;
46
+ const [items, total] = await findAndCountWithDecryption(
47
+ em,
48
+ SyncRun,
49
+ where,
50
+ {
51
+ orderBy: { createdAt: "DESC" },
52
+ limit: query.pageSize,
53
+ offset: (query.page - 1) * query.pageSize
54
+ },
55
+ scope
56
+ );
57
+ return { items, total };
58
+ },
59
+ async markStatus(runId, status, scope, error) {
60
+ const row = await this.getRun(runId, scope);
61
+ if (!row) return null;
62
+ row.status = status;
63
+ if (error !== void 0) row.lastError = error;
64
+ await em.flush();
65
+ return row;
66
+ },
67
+ async updateCounts(runId, delta, scope) {
68
+ const row = await this.getRun(runId, scope);
69
+ if (!row) return null;
70
+ row.createdCount += delta.createdCount ?? 0;
71
+ row.updatedCount += delta.updatedCount ?? 0;
72
+ row.skippedCount += delta.skippedCount ?? 0;
73
+ row.failedCount += delta.failedCount ?? 0;
74
+ row.batchesCompleted += delta.batchesCompleted ?? 0;
75
+ await em.flush();
76
+ return row;
77
+ },
78
+ async updateCursor(runId, cursor, scope) {
79
+ const run = await this.getRun(runId, scope);
80
+ if (!run) return;
81
+ run.cursor = cursor;
82
+ const cursorRow = await findOneWithDecryption(
83
+ em,
84
+ SyncCursor,
85
+ {
86
+ integrationId: run.integrationId,
87
+ entityType: run.entityType,
88
+ direction: run.direction,
89
+ organizationId: scope.organizationId,
90
+ tenantId: scope.tenantId
91
+ },
92
+ void 0,
93
+ scope
94
+ );
95
+ if (cursorRow) {
96
+ cursorRow.cursor = cursor;
97
+ } else {
98
+ em.create(SyncCursor, {
99
+ integrationId: run.integrationId,
100
+ entityType: run.entityType,
101
+ direction: run.direction,
102
+ cursor,
103
+ organizationId: scope.organizationId,
104
+ tenantId: scope.tenantId
105
+ });
106
+ }
107
+ await em.flush();
108
+ },
109
+ async resolveCursor(integrationId, entityType, direction, scope) {
110
+ const row = await findOneWithDecryption(
111
+ em,
112
+ SyncCursor,
113
+ {
114
+ integrationId,
115
+ entityType,
116
+ direction,
117
+ organizationId: scope.organizationId,
118
+ tenantId: scope.tenantId
119
+ },
120
+ void 0,
121
+ scope
122
+ );
123
+ return row?.cursor ?? null;
124
+ },
125
+ async findRunningOverlap(integrationId, entityType, direction, scope) {
126
+ const [run] = await findWithDecryption(
127
+ em,
128
+ SyncRun,
129
+ {
130
+ integrationId,
131
+ entityType,
132
+ direction,
133
+ status: "running",
134
+ organizationId: scope.organizationId,
135
+ tenantId: scope.tenantId,
136
+ deletedAt: null
137
+ },
138
+ { limit: 1 },
139
+ scope
140
+ );
141
+ return run ?? null;
142
+ }
143
+ };
144
+ }
145
+ export {
146
+ createSyncRunService
147
+ };
148
+ //# sourceMappingURL=sync-run-service.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/data_sync/lib/sync-run-service.ts"],
4
+ "sourcesContent": ["import type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport { findAndCountWithDecryption, findOneWithDecryption, findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { SyncCursor, SyncRun } from '../data/entities'\n\ntype SyncScope = {\n organizationId: string\n tenantId: string\n}\n\nexport function createSyncRunService(em: EntityManager) {\n return {\n async createRun(input: {\n integrationId: string\n entityType: string\n direction: 'import' | 'export'\n cursor?: string | null\n triggeredBy?: string | null\n progressJobId?: string | null\n jobId?: string | null\n }, scope: SyncScope): Promise<SyncRun> {\n const row = em.create(SyncRun, {\n integrationId: input.integrationId,\n entityType: input.entityType,\n direction: input.direction,\n status: 'pending',\n cursor: input.cursor,\n initialCursor: input.cursor,\n triggeredBy: input.triggeredBy,\n progressJobId: input.progressJobId,\n jobId: input.jobId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n })\n\n await em.persistAndFlush(row)\n return row\n },\n\n async getRun(runId: string, scope: SyncScope): Promise<SyncRun | null> {\n return findOneWithDecryption(\n em,\n SyncRun,\n {\n id: runId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n },\n\n async listRuns(query: {\n integrationId?: string\n entityType?: string\n direction?: 'import' | 'export'\n status?: string\n page: number\n pageSize: number\n }, scope: SyncScope): Promise<{ items: SyncRun[]; total: number }> {\n const where: FilterQuery<SyncRun> = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n }\n\n if (query.integrationId) where.integrationId = query.integrationId\n if (query.entityType) where.entityType = query.entityType\n if (query.direction) where.direction = query.direction\n if (query.status) where.status = query.status as SyncRun['status']\n\n const [items, total] = await findAndCountWithDecryption(\n em,\n SyncRun,\n where,\n {\n orderBy: { createdAt: 'DESC' },\n limit: query.pageSize,\n offset: (query.page - 1) * query.pageSize,\n },\n scope,\n )\n\n return { items, total }\n },\n\n async markStatus(runId: string, status: SyncRun['status'], scope: SyncScope, error?: string): Promise<SyncRun | null> {\n const row = await this.getRun(runId, scope)\n if (!row) return null\n row.status = status\n if (error !== undefined) row.lastError = error\n await em.flush()\n return row\n },\n\n async updateCounts(\n runId: string,\n delta: Partial<Pick<SyncRun, 'createdCount' | 'updatedCount' | 'skippedCount' | 'failedCount' | 'batchesCompleted'>>,\n scope: SyncScope,\n ): Promise<SyncRun | null> {\n const row = await this.getRun(runId, scope)\n if (!row) return null\n\n row.createdCount += delta.createdCount ?? 0\n row.updatedCount += delta.updatedCount ?? 0\n row.skippedCount += delta.skippedCount ?? 0\n row.failedCount += delta.failedCount ?? 0\n row.batchesCompleted += delta.batchesCompleted ?? 0\n await em.flush()\n return row\n },\n\n async updateCursor(runId: string, cursor: string, scope: SyncScope): Promise<void> {\n const run = await this.getRun(runId, scope)\n if (!run) return\n run.cursor = cursor\n\n const cursorRow = await findOneWithDecryption(\n em,\n SyncCursor,\n {\n integrationId: run.integrationId,\n entityType: run.entityType,\n direction: run.direction,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n },\n undefined,\n scope,\n )\n\n if (cursorRow) {\n cursorRow.cursor = cursor\n } else {\n em.create(SyncCursor, {\n integrationId: run.integrationId,\n entityType: run.entityType,\n direction: run.direction,\n cursor,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n })\n }\n\n await em.flush()\n },\n\n async resolveCursor(integrationId: string, entityType: string, direction: 'import' | 'export', scope: SyncScope): Promise<string | null> {\n const row = await findOneWithDecryption(\n em,\n SyncCursor,\n {\n integrationId,\n entityType,\n direction,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n },\n undefined,\n scope,\n )\n return row?.cursor ?? null\n },\n\n async findRunningOverlap(integrationId: string, entityType: string, direction: 'import' | 'export', scope: SyncScope): Promise<SyncRun | null> {\n const [run] = await findWithDecryption(\n em,\n SyncRun,\n {\n integrationId,\n entityType,\n direction,\n status: 'running',\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n { limit: 1 },\n scope,\n )\n return run ?? null\n },\n }\n}\n\nexport type SyncRunService = ReturnType<typeof createSyncRunService>\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }
@@ -0,0 +1,17 @@
1
+ import { Migration } from "@mikro-orm/migrations";
2
+ class Migration20260304113737 extends Migration {
3
+ async up() {
4
+ this.addSql(`create table "sync_cursors" ("id" uuid not null default gen_random_uuid(), "integration_id" text not null, "entity_type" text not null, "direction" text not null, "cursor" text null, "organization_id" uuid not null, "tenant_id" uuid not null, "updated_at" timestamptz not null, constraint "sync_cursors_pkey" primary key ("id"));`);
5
+ this.addSql(`create unique index "sync_cursors_integration_id_entity_type_direction__b4d87_index" on "sync_cursors" ("integration_id", "entity_type", "direction", "organization_id", "tenant_id");`);
6
+ this.addSql(`create table "sync_mappings" ("id" uuid not null default gen_random_uuid(), "integration_id" text not null, "entity_type" text not null, "mapping" jsonb not null, "organization_id" uuid not null, "tenant_id" uuid not null, "created_at" timestamptz not null, "updated_at" timestamptz not null, constraint "sync_mappings_pkey" primary key ("id"));`);
7
+ this.addSql(`create unique index "sync_mappings_integration_id_entity_type_organizat_edee9_index" on "sync_mappings" ("integration_id", "entity_type", "organization_id", "tenant_id");`);
8
+ this.addSql(`create table "sync_runs" ("id" uuid not null default gen_random_uuid(), "integration_id" text not null, "entity_type" text not null, "direction" text not null, "status" text not null, "cursor" text null, "initial_cursor" text null, "created_count" int not null default 0, "updated_count" int not null default 0, "skipped_count" int not null default 0, "failed_count" int not null default 0, "batches_completed" int not null default 0, "last_error" text null, "progress_job_id" uuid null, "job_id" text null, "triggered_by" text null, "organization_id" uuid not null, "tenant_id" uuid not null, "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, constraint "sync_runs_pkey" primary key ("id"));`);
9
+ this.addSql(`create index "sync_runs_integration_id_entity_type_status_organi_8b13b_index" on "sync_runs" ("integration_id", "entity_type", "status", "organization_id", "tenant_id");`);
10
+ this.addSql(`create table "sync_schedules" ("id" uuid not null default gen_random_uuid(), "integration_id" text not null, "entity_type" text not null, "direction" text not null, "schedule_type" text not null, "schedule_value" text not null, "timezone" text not null default 'UTC', "full_sync" boolean not null default false, "is_enabled" boolean not null default true, "scheduled_job_id" uuid null, "last_run_at" timestamptz null, "organization_id" uuid not null, "tenant_id" uuid not null, "created_at" timestamptz not null, "updated_at" timestamptz not null, "deleted_at" timestamptz null, constraint "sync_schedules_pkey" primary key ("id"));`);
11
+ this.addSql(`create index "sync_schedules_integration_id_entity_type_directio_addb9_index" on "sync_schedules" ("integration_id", "entity_type", "direction", "organization_id", "tenant_id");`);
12
+ }
13
+ }
14
+ export {
15
+ Migration20260304113737
16
+ };
17
+ //# sourceMappingURL=Migration20260304113737.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/data_sync/migrations/Migration20260304113737.ts"],
4
+ "sourcesContent": ["import { Migration } from '@mikro-orm/migrations';\n\nexport class Migration20260304113737 extends Migration {\n\n override async up(): Promise<void> {\n this.addSql(`create table \"sync_cursors\" (\"id\" uuid not null default gen_random_uuid(), \"integration_id\" text not null, \"entity_type\" text not null, \"direction\" text not null, \"cursor\" text null, \"organization_id\" uuid not null, \"tenant_id\" uuid not null, \"updated_at\" timestamptz not null, constraint \"sync_cursors_pkey\" primary key (\"id\"));`);\n this.addSql(`create unique index \"sync_cursors_integration_id_entity_type_direction__b4d87_index\" on \"sync_cursors\" (\"integration_id\", \"entity_type\", \"direction\", \"organization_id\", \"tenant_id\");`);\n\n this.addSql(`create table \"sync_mappings\" (\"id\" uuid not null default gen_random_uuid(), \"integration_id\" text not null, \"entity_type\" text not null, \"mapping\" jsonb not null, \"organization_id\" uuid not null, \"tenant_id\" uuid not null, \"created_at\" timestamptz not null, \"updated_at\" timestamptz not null, constraint \"sync_mappings_pkey\" primary key (\"id\"));`);\n this.addSql(`create unique index \"sync_mappings_integration_id_entity_type_organizat_edee9_index\" on \"sync_mappings\" (\"integration_id\", \"entity_type\", \"organization_id\", \"tenant_id\");`);\n\n this.addSql(`create table \"sync_runs\" (\"id\" uuid not null default gen_random_uuid(), \"integration_id\" text not null, \"entity_type\" text not null, \"direction\" text not null, \"status\" text not null, \"cursor\" text null, \"initial_cursor\" text null, \"created_count\" int not null default 0, \"updated_count\" int not null default 0, \"skipped_count\" int not null default 0, \"failed_count\" int not null default 0, \"batches_completed\" int not null default 0, \"last_error\" text null, \"progress_job_id\" uuid null, \"job_id\" text null, \"triggered_by\" text null, \"organization_id\" uuid not null, \"tenant_id\" uuid not null, \"created_at\" timestamptz not null, \"updated_at\" timestamptz not null, \"deleted_at\" timestamptz null, constraint \"sync_runs_pkey\" primary key (\"id\"));`);\n this.addSql(`create index \"sync_runs_integration_id_entity_type_status_organi_8b13b_index\" on \"sync_runs\" (\"integration_id\", \"entity_type\", \"status\", \"organization_id\", \"tenant_id\");`);\n\n this.addSql(`create table \"sync_schedules\" (\"id\" uuid not null default gen_random_uuid(), \"integration_id\" text not null, \"entity_type\" text not null, \"direction\" text not null, \"schedule_type\" text not null, \"schedule_value\" text not null, \"timezone\" text not null default 'UTC', \"full_sync\" boolean not null default false, \"is_enabled\" boolean not null default true, \"scheduled_job_id\" uuid null, \"last_run_at\" timestamptz null, \"organization_id\" uuid not null, \"tenant_id\" uuid not null, \"created_at\" timestamptz not null, \"updated_at\" timestamptz not null, \"deleted_at\" timestamptz null, constraint \"sync_schedules_pkey\" primary key (\"id\"));`);\n this.addSql(`create index \"sync_schedules_integration_id_entity_type_directio_addb9_index\" on \"sync_schedules\" (\"integration_id\", \"entity_type\", \"direction\", \"organization_id\", \"tenant_id\");`);\n }\n\n}\n"],
5
+ "mappings": "AAAA,SAAS,iBAAiB;AAEnB,MAAM,gCAAgC,UAAU;AAAA,EAErD,MAAe,KAAoB;AACjC,SAAK,OAAO,2UAA2U;AACvV,SAAK,OAAO,wLAAwL;AAEpM,SAAK,OAAO,2VAA2V;AACvW,SAAK,OAAO,4KAA4K;AAExL,SAAK,OAAO,yuBAAyuB;AACrvB,SAAK,OAAO,2KAA2K;AAEvL,SAAK,OAAO,0nBAA0nB;AACtoB,SAAK,OAAO,mLAAmL;AAAA,EACjM;AAEF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,13 @@
1
+ const setup = {
2
+ defaultRoleFeatures: {
3
+ superadmin: ["data_sync.view", "data_sync.run", "data_sync.configure"],
4
+ admin: ["data_sync.view", "data_sync.run", "data_sync.configure"],
5
+ employee: ["data_sync.view"]
6
+ }
7
+ };
8
+ var setup_default = setup;
9
+ export {
10
+ setup_default as default,
11
+ setup
12
+ };
13
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../src/modules/data_sync/setup.ts"],
4
+ "sourcesContent": ["import type { ModuleSetupConfig } from '@open-mercato/shared/modules/setup'\n\nexport const setup: ModuleSetupConfig = {\n defaultRoleFeatures: {\n superadmin: ['data_sync.view', 'data_sync.run', 'data_sync.configure'],\n admin: ['data_sync.view', 'data_sync.run', 'data_sync.configure'],\n employee: ['data_sync.view'],\n },\n}\n\nexport default setup\n"],
5
+ "mappings": "AAEO,MAAM,QAA2B;AAAA,EACtC,qBAAqB;AAAA,IACnB,YAAY,CAAC,kBAAkB,iBAAiB,qBAAqB;AAAA,IACrE,OAAO,CAAC,kBAAkB,iBAAiB,qBAAqB;AAAA,IAChE,UAAU,CAAC,gBAAgB;AAAA,EAC7B;AACF;AAEA,IAAO,gBAAQ;",
6
+ "names": []
7
+ }
@@ -0,0 +1,14 @@
1
+ const metadata = {
2
+ queue: "data-sync-export",
3
+ id: "data-sync:export",
4
+ concurrency: 5
5
+ };
6
+ async function handle(job, ctx) {
7
+ const engine = ctx.resolve("dataSyncEngine");
8
+ await engine.runExport(job.payload.runId, job.payload.batchSize, job.payload.scope);
9
+ }
10
+ export {
11
+ handle as default,
12
+ metadata
13
+ };
14
+ //# sourceMappingURL=sync-export.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/data_sync/workers/sync-export.ts"],
4
+ "sourcesContent": ["import type { JobContext, QueuedJob, WorkerMeta } from '@open-mercato/queue'\nimport type { SyncEngine } from '../lib/sync-engine'\n\ntype SyncJobPayload = {\n runId: string\n batchSize: number\n scope: {\n organizationId: string\n tenantId: string\n userId?: string | null\n }\n}\n\nexport const metadata: WorkerMeta = {\n queue: 'data-sync-export',\n id: 'data-sync:export',\n concurrency: 5,\n}\n\ntype HandlerContext = JobContext & {\n resolve: <T = unknown>(name: string) => T\n}\n\nexport default async function handle(job: QueuedJob<SyncJobPayload>, ctx: HandlerContext): Promise<void> {\n const engine = ctx.resolve<SyncEngine>('dataSyncEngine')\n await engine.runExport(job.payload.runId, job.payload.batchSize, job.payload.scope)\n}\n"],
5
+ "mappings": "AAaO,MAAM,WAAuB;AAAA,EAClC,OAAO;AAAA,EACP,IAAI;AAAA,EACJ,aAAa;AACf;AAMA,eAAO,OAA8B,KAAgC,KAAoC;AACvG,QAAM,SAAS,IAAI,QAAoB,gBAAgB;AACvD,QAAM,OAAO,UAAU,IAAI,QAAQ,OAAO,IAAI,QAAQ,WAAW,IAAI,QAAQ,KAAK;AACpF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,14 @@
1
+ const metadata = {
2
+ queue: "data-sync-import",
3
+ id: "data-sync:import",
4
+ concurrency: 5
5
+ };
6
+ async function handle(job, ctx) {
7
+ const engine = ctx.resolve("dataSyncEngine");
8
+ await engine.runImport(job.payload.runId, job.payload.batchSize, job.payload.scope);
9
+ }
10
+ export {
11
+ handle as default,
12
+ metadata
13
+ };
14
+ //# sourceMappingURL=sync-import.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/data_sync/workers/sync-import.ts"],
4
+ "sourcesContent": ["import type { JobContext, QueuedJob, WorkerMeta } from '@open-mercato/queue'\nimport type { SyncEngine } from '../lib/sync-engine'\n\ntype SyncJobPayload = {\n runId: string\n batchSize: number\n scope: {\n organizationId: string\n tenantId: string\n userId?: string | null\n }\n}\n\nexport const metadata: WorkerMeta = {\n queue: 'data-sync-import',\n id: 'data-sync:import',\n concurrency: 5,\n}\n\ntype HandlerContext = JobContext & {\n resolve: <T = unknown>(name: string) => T\n}\n\nexport default async function handle(job: QueuedJob<SyncJobPayload>, ctx: HandlerContext): Promise<void> {\n const engine = ctx.resolve<SyncEngine>('dataSyncEngine')\n await engine.runImport(job.payload.runId, job.payload.batchSize, job.payload.scope)\n}\n"],
5
+ "mappings": "AAaO,MAAM,WAAuB;AAAA,EAClC,OAAO;AAAA,EACP,IAAI;AAAA,EACJ,aAAa;AACf;AAMA,eAAO,OAA8B,KAAgC,KAAoC;AACvG,QAAM,SAAS,IAAI,QAAoB,gBAAgB;AACvD,QAAM,OAAO,UAAU,IAAI,QAAQ,OAAO,IAAI,QAAQ,WAAW,IAAI,QAAQ,KAAK;AACpF;",
6
+ "names": []
7
+ }
@@ -0,0 +1,63 @@
1
+ import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
2
+ import { SyncSchedule } from "../data/entities.js";
3
+ import { getSyncQueue } from "../lib/queue.js";
4
+ const metadata = {
5
+ queue: "data-sync-scheduled",
6
+ id: "data-sync:scheduled",
7
+ concurrency: 3
8
+ };
9
+ async function handle(job, ctx) {
10
+ const em = ctx.resolve("em");
11
+ const syncRunService = ctx.resolve("dataSyncRunService");
12
+ const schedule = await findOneWithDecryption(
13
+ em,
14
+ SyncSchedule,
15
+ {
16
+ id: job.payload.scheduleId,
17
+ organizationId: job.payload.scope.organizationId,
18
+ tenantId: job.payload.scope.tenantId,
19
+ deletedAt: null
20
+ },
21
+ void 0,
22
+ job.payload.scope
23
+ );
24
+ if (!schedule || !schedule.isEnabled) {
25
+ return;
26
+ }
27
+ const overlap = await syncRunService.findRunningOverlap(
28
+ schedule.integrationId,
29
+ schedule.entityType,
30
+ schedule.direction,
31
+ job.payload.scope
32
+ );
33
+ if (overlap) {
34
+ return;
35
+ }
36
+ const cursor = schedule.fullSync ? null : await syncRunService.resolveCursor(
37
+ schedule.integrationId,
38
+ schedule.entityType,
39
+ schedule.direction,
40
+ job.payload.scope
41
+ );
42
+ const run = await syncRunService.createRun({
43
+ integrationId: schedule.integrationId,
44
+ entityType: schedule.entityType,
45
+ direction: schedule.direction,
46
+ cursor,
47
+ triggeredBy: "scheduler"
48
+ }, job.payload.scope);
49
+ schedule.lastRunAt = /* @__PURE__ */ new Date();
50
+ await em.flush();
51
+ const queueName = schedule.direction === "import" ? "data-sync-import" : "data-sync-export";
52
+ const queue = getSyncQueue(queueName);
53
+ await queue.enqueue({
54
+ runId: run.id,
55
+ batchSize: 100,
56
+ scope: job.payload.scope
57
+ });
58
+ }
59
+ export {
60
+ handle as default,
61
+ metadata
62
+ };
63
+ //# sourceMappingURL=sync-scheduled.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/data_sync/workers/sync-scheduled.ts"],
4
+ "sourcesContent": ["import type { JobContext, QueuedJob, WorkerMeta } from '@open-mercato/queue'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport type { SyncRunService } from '../lib/sync-run-service'\nimport { SyncSchedule } from '../data/entities'\nimport { getSyncQueue } from '../lib/queue'\n\ntype ScheduledSyncPayload = {\n scheduleId: string\n scope: {\n organizationId: string\n tenantId: string\n }\n}\n\nexport const metadata: WorkerMeta = {\n queue: 'data-sync-scheduled',\n id: 'data-sync:scheduled',\n concurrency: 3,\n}\n\ntype HandlerContext = JobContext & {\n resolve: <T = unknown>(name: string) => T\n}\n\nexport default async function handle(job: QueuedJob<ScheduledSyncPayload>, ctx: HandlerContext): Promise<void> {\n const em = ctx.resolve<EntityManager>('em')\n const syncRunService = ctx.resolve<SyncRunService>('dataSyncRunService')\n\n const schedule = await findOneWithDecryption(\n em,\n SyncSchedule,\n {\n id: job.payload.scheduleId,\n organizationId: job.payload.scope.organizationId,\n tenantId: job.payload.scope.tenantId,\n deletedAt: null,\n },\n undefined,\n job.payload.scope,\n )\n\n if (!schedule || !schedule.isEnabled) {\n return\n }\n\n const overlap = await syncRunService.findRunningOverlap(\n schedule.integrationId,\n schedule.entityType,\n schedule.direction,\n job.payload.scope,\n )\n if (overlap) {\n return\n }\n\n const cursor = schedule.fullSync\n ? null\n : await syncRunService.resolveCursor(\n schedule.integrationId,\n schedule.entityType,\n schedule.direction,\n job.payload.scope,\n )\n\n const run = await syncRunService.createRun({\n integrationId: schedule.integrationId,\n entityType: schedule.entityType,\n direction: schedule.direction,\n cursor,\n triggeredBy: 'scheduler',\n }, job.payload.scope)\n\n schedule.lastRunAt = new Date()\n await em.flush()\n\n const queueName = schedule.direction === 'import' ? 'data-sync-import' : 'data-sync-export'\n const queue = getSyncQueue(queueName)\n await queue.enqueue({\n runId: run.id,\n batchSize: 100,\n scope: job.payload.scope,\n })\n}\n"],
5
+ "mappings": "AAEA,SAAS,6BAA6B;AAEtC,SAAS,oBAAoB;AAC7B,SAAS,oBAAoB;AAUtB,MAAM,WAAuB;AAAA,EAClC,OAAO;AAAA,EACP,IAAI;AAAA,EACJ,aAAa;AACf;AAMA,eAAO,OAA8B,KAAsC,KAAoC;AAC7G,QAAM,KAAK,IAAI,QAAuB,IAAI;AAC1C,QAAM,iBAAiB,IAAI,QAAwB,oBAAoB;AAEvE,QAAM,WAAW,MAAM;AAAA,IACrB;AAAA,IACA;AAAA,IACA;AAAA,MACE,IAAI,IAAI,QAAQ;AAAA,MAChB,gBAAgB,IAAI,QAAQ,MAAM;AAAA,MAClC,UAAU,IAAI,QAAQ,MAAM;AAAA,MAC5B,WAAW;AAAA,IACb;AAAA,IACA;AAAA,IACA,IAAI,QAAQ;AAAA,EACd;AAEA,MAAI,CAAC,YAAY,CAAC,SAAS,WAAW;AACpC;AAAA,EACF;AAEA,QAAM,UAAU,MAAM,eAAe;AAAA,IACnC,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,IAAI,QAAQ;AAAA,EACd;AACA,MAAI,SAAS;AACX;AAAA,EACF;AAEA,QAAM,SAAS,SAAS,WACpB,OACA,MAAM,eAAe;AAAA,IACnB,SAAS;AAAA,IACT,SAAS;AAAA,IACT,SAAS;AAAA,IACT,IAAI,QAAQ;AAAA,EACd;AAEJ,QAAM,MAAM,MAAM,eAAe,UAAU;AAAA,IACzC,eAAe,SAAS;AAAA,IACxB,YAAY,SAAS;AAAA,IACrB,WAAW,SAAS;AAAA,IACpB;AAAA,IACA,aAAa;AAAA,EACf,GAAG,IAAI,QAAQ,KAAK;AAEpB,WAAS,YAAY,oBAAI,KAAK;AAC9B,QAAM,GAAG,MAAM;AAEf,QAAM,YAAY,SAAS,cAAc,WAAW,qBAAqB;AACzE,QAAM,QAAQ,aAAa,SAAS;AACpC,QAAM,MAAM,QAAQ;AAAA,IAClB,OAAO,IAAI;AAAA,IACX,WAAW;AAAA,IACX,OAAO,IAAI,QAAQ;AAAA,EACrB,CAAC;AACH;",
6
+ "names": []
7
+ }
@@ -144,6 +144,10 @@ const DEFAULT_ENCRYPTION_MAPS = [
144
144
  { field: "context_json" }
145
145
  ]
146
146
  },
147
+ {
148
+ entityId: "integrations:integration_credentials",
149
+ fields: [{ field: "credentials" }]
150
+ },
147
151
  {
148
152
  entityId: "staff:staff_leave_request",
149
153
  fields: [
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/entities/lib/encryptionDefaults.ts"],
4
- "sourcesContent": ["export const DEFAULT_ENCRYPTION_MAPS: Array<{ entityId: string; fields: Array<{ field: string; hashField?: string | null }> }> = [\n {\n entityId: 'auth:user',\n fields: [{ field: 'email', hashField: 'email_hash' }],\n },\n {\n entityId: 'customers:customer_address',\n fields: [\n { field: 'name' },\n { field: 'company_name' },\n { field: 'address_line1' },\n { field: 'address_line2' },\n { field: 'city' },\n { field: 'region' },\n { field: 'postal_code' },\n { field: 'country' },\n { field: 'building_number' },\n { field: 'flat_number' },\n ],\n },\n {\n entityId: 'customers:customer_entity',\n fields: [\n { field: 'display_name' },\n { field: 'primary_email' },\n { field: 'primary_phone' },\n { field: 'next_interaction_name' },\n { field: 'description' },\n ],\n },\n {\n entityId: 'customers:customer_deal',\n fields: [\n { field: 'title' },\n { field: 'description' },\n ],\n },\n {\n entityId: 'customers:customer_activity',\n fields: [\n { field: 'subject' },\n { field: 'body' },\n ],\n },\n {\n entityId: 'customers:customer_comment',\n fields: [{ field: 'body' }],\n },\n {\n entityId: 'customers:customer_person_profile',\n fields: [\n { field: 'first_name' },\n { field: 'last_name' },\n { field: 'preferred_name' },\n { field: 'job_title' },\n { field: 'department' },\n { field: 'seniority' },\n { field: 'timezone' },\n { field: 'linked_in_url' },\n { field: 'twitter_url' },\n ],\n },\n {\n entityId: 'customers:customer_company_profile',\n fields: [\n { field: 'legal_name' },\n { field: 'brand_name' },\n { field: 'domain' },\n { field: 'website_url' },\n { field: 'industry' },\n ],\n },\n {\n entityId: 'sales:sales_order',\n fields: [\n { field: 'customer_snapshot' },\n { field: 'billing_address_snapshot' },\n { field: 'shipping_address_snapshot' },\n { field: 'shipping_method_snapshot' },\n { field: 'delivery_window_snapshot' },\n { field: 'payment_method_snapshot' },\n { field: 'totals_snapshot' },\n { field: 'catalog_snapshot' },\n { field: 'promotion_snapshot' },\n { field: 'comments' },\n { field: 'internal_notes' },\n { field: 'metadata' },\n ],\n },\n {\n entityId: 'sales:sales_quote',\n fields: [\n { field: 'customer_snapshot' },\n { field: 'billing_address_snapshot' },\n { field: 'shipping_address_snapshot' },\n { field: 'shipping_method_snapshot' },\n { field: 'delivery_window_snapshot' },\n { field: 'payment_method_snapshot' },\n { field: 'totals_snapshot' },\n { field: 'catalog_snapshot' },\n { field: 'promotion_snapshot' },\n { field: 'comments' },\n { field: 'internal_notes' },\n { field: 'metadata' },\n ],\n },\n {\n entityId: 'sales:sales_document_address',\n fields: [\n { field: 'name' },\n { field: 'purpose' },\n { field: 'company_name' },\n { field: 'address_line1' },\n { field: 'address_line2' },\n { field: 'city' },\n { field: 'region' },\n { field: 'postal_code' },\n { field: 'country' },\n { field: 'building_number' },\n { field: 'flat_number' },\n ],\n },\n {\n entityId: 'sales:sales_note',\n fields: [{ field: 'body' }],\n },\n {\n entityId: 'audit_logs:action_log',\n fields: [\n { field: 'command_id' },\n { field: 'action_label' },\n { field: 'command_payload' },\n { field: 'snapshot_before' },\n { field: 'snapshot_after' },\n { field: 'changes_json' },\n { field: 'context_json' },\n ],\n },\n {\n entityId: 'audit_logs:access_log',\n fields: [\n { field: 'resource_id' },\n { field: 'fields_json' },\n { field: 'context_json' },\n ],\n },\n {\n entityId: 'staff:staff_leave_request',\n fields: [\n { field: 'note' },\n { field: 'decision_comment' },\n { field: 'unavailability_reason_value' },\n ],\n },\n {\n entityId: 'vector:vector_search',\n fields: [\n { field: 'links' },\n { field: 'payload' },\n { field: 'result_title' },\n { field: 'result_subtitle' },\n { field: 'result_icon' },\n { field: 'result_badge' },\n { field: 'result_snapshot' },\n { field: 'primary_link_href' },\n { field: 'primary_link_label' },\n ],\n }\n]\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["export const DEFAULT_ENCRYPTION_MAPS: Array<{ entityId: string; fields: Array<{ field: string; hashField?: string | null }> }> = [\n {\n entityId: 'auth:user',\n fields: [{ field: 'email', hashField: 'email_hash' }],\n },\n {\n entityId: 'customers:customer_address',\n fields: [\n { field: 'name' },\n { field: 'company_name' },\n { field: 'address_line1' },\n { field: 'address_line2' },\n { field: 'city' },\n { field: 'region' },\n { field: 'postal_code' },\n { field: 'country' },\n { field: 'building_number' },\n { field: 'flat_number' },\n ],\n },\n {\n entityId: 'customers:customer_entity',\n fields: [\n { field: 'display_name' },\n { field: 'primary_email' },\n { field: 'primary_phone' },\n { field: 'next_interaction_name' },\n { field: 'description' },\n ],\n },\n {\n entityId: 'customers:customer_deal',\n fields: [\n { field: 'title' },\n { field: 'description' },\n ],\n },\n {\n entityId: 'customers:customer_activity',\n fields: [\n { field: 'subject' },\n { field: 'body' },\n ],\n },\n {\n entityId: 'customers:customer_comment',\n fields: [{ field: 'body' }],\n },\n {\n entityId: 'customers:customer_person_profile',\n fields: [\n { field: 'first_name' },\n { field: 'last_name' },\n { field: 'preferred_name' },\n { field: 'job_title' },\n { field: 'department' },\n { field: 'seniority' },\n { field: 'timezone' },\n { field: 'linked_in_url' },\n { field: 'twitter_url' },\n ],\n },\n {\n entityId: 'customers:customer_company_profile',\n fields: [\n { field: 'legal_name' },\n { field: 'brand_name' },\n { field: 'domain' },\n { field: 'website_url' },\n { field: 'industry' },\n ],\n },\n {\n entityId: 'sales:sales_order',\n fields: [\n { field: 'customer_snapshot' },\n { field: 'billing_address_snapshot' },\n { field: 'shipping_address_snapshot' },\n { field: 'shipping_method_snapshot' },\n { field: 'delivery_window_snapshot' },\n { field: 'payment_method_snapshot' },\n { field: 'totals_snapshot' },\n { field: 'catalog_snapshot' },\n { field: 'promotion_snapshot' },\n { field: 'comments' },\n { field: 'internal_notes' },\n { field: 'metadata' },\n ],\n },\n {\n entityId: 'sales:sales_quote',\n fields: [\n { field: 'customer_snapshot' },\n { field: 'billing_address_snapshot' },\n { field: 'shipping_address_snapshot' },\n { field: 'shipping_method_snapshot' },\n { field: 'delivery_window_snapshot' },\n { field: 'payment_method_snapshot' },\n { field: 'totals_snapshot' },\n { field: 'catalog_snapshot' },\n { field: 'promotion_snapshot' },\n { field: 'comments' },\n { field: 'internal_notes' },\n { field: 'metadata' },\n ],\n },\n {\n entityId: 'sales:sales_document_address',\n fields: [\n { field: 'name' },\n { field: 'purpose' },\n { field: 'company_name' },\n { field: 'address_line1' },\n { field: 'address_line2' },\n { field: 'city' },\n { field: 'region' },\n { field: 'postal_code' },\n { field: 'country' },\n { field: 'building_number' },\n { field: 'flat_number' },\n ],\n },\n {\n entityId: 'sales:sales_note',\n fields: [{ field: 'body' }],\n },\n {\n entityId: 'audit_logs:action_log',\n fields: [\n { field: 'command_id' },\n { field: 'action_label' },\n { field: 'command_payload' },\n { field: 'snapshot_before' },\n { field: 'snapshot_after' },\n { field: 'changes_json' },\n { field: 'context_json' },\n ],\n },\n {\n entityId: 'audit_logs:access_log',\n fields: [\n { field: 'resource_id' },\n { field: 'fields_json' },\n { field: 'context_json' },\n ],\n },\n {\n entityId: 'integrations:integration_credentials',\n fields: [{ field: 'credentials' }],\n },\n {\n entityId: 'staff:staff_leave_request',\n fields: [\n { field: 'note' },\n { field: 'decision_comment' },\n { field: 'unavailability_reason_value' },\n ],\n },\n {\n entityId: 'vector:vector_search',\n fields: [\n { field: 'links' },\n { field: 'payload' },\n { field: 'result_title' },\n { field: 'result_subtitle' },\n { field: 'result_icon' },\n { field: 'result_badge' },\n { field: 'result_snapshot' },\n { field: 'primary_link_href' },\n { field: 'primary_link_label' },\n ],\n }\n]\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1,8 +1,11 @@
1
1
  const features = [
2
2
  { id: "integrations.view", title: "View integrations and external ID mappings", module: "integrations" },
3
- { id: "integrations.manage", title: "Manage integration configurations", module: "integrations" }
3
+ { id: "integrations.manage", title: "Manage integration configurations", module: "integrations" },
4
+ { id: "integrations.credentials.manage", title: "Manage integration credentials", module: "integrations" }
4
5
  ];
6
+ var acl_default = features;
5
7
  export {
8
+ acl_default as default,
6
9
  features
7
10
  };
8
11
  //# sourceMappingURL=acl.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
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;",
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 { id: 'integrations.credentials.manage', title: 'Manage integration credentials', module: 'integrations' },\n]\n\nexport default features\n"],
5
+ "mappings": "AAAO,MAAM,WAAW;AAAA,EACtB,EAAE,IAAI,qBAAqB,OAAO,8CAA8C,QAAQ,eAAe;AAAA,EACvG,EAAE,IAAI,uBAAuB,OAAO,qCAAqC,QAAQ,eAAe;AAAA,EAChG,EAAE,IAAI,mCAAmC,OAAO,kCAAkC,QAAQ,eAAe;AAC3G;AAEA,IAAO,cAAQ;",
6
6
  "names": []
7
7
  }
@@ -0,0 +1,127 @@
1
+ import { NextResponse } from "next/server";
2
+ import { z } from "zod";
3
+ import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
4
+ import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
5
+ import { getIntegration } from "@open-mercato/shared/modules/integrations/types";
6
+ import { emitIntegrationsEvent } from "../../../events.js";
7
+ import { saveCredentialsSchema } from "../../../data/validators.js";
8
+ import {
9
+ resolveUserFeatures,
10
+ runIntegrationMutationGuardAfterSuccess,
11
+ runIntegrationMutationGuards
12
+ } from "../../guards.js";
13
+ const idParamsSchema = z.object({ id: z.string().min(1) });
14
+ const metadata = {
15
+ GET: { requireAuth: true, requireFeatures: ["integrations.credentials.manage"] },
16
+ PUT: { requireAuth: true, requireFeatures: ["integrations.credentials.manage"] }
17
+ };
18
+ const openApi = {
19
+ tags: ["Integrations"],
20
+ summary: "Get or save integration credentials"
21
+ };
22
+ function resolveParams(ctx) {
23
+ if (!ctx.params) return void 0;
24
+ if (typeof ctx.params.then === "function") {
25
+ return ctx.params;
26
+ }
27
+ return ctx.params;
28
+ }
29
+ async function GET(req, ctx) {
30
+ const auth = await getAuthFromRequest(req);
31
+ if (!auth?.tenantId || !auth.orgId) {
32
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
33
+ }
34
+ const rawParams = await resolveParams(ctx);
35
+ const parsedParams = idParamsSchema.safeParse(rawParams);
36
+ if (!parsedParams.success) {
37
+ return NextResponse.json({ error: "Invalid integration id" }, { status: 400 });
38
+ }
39
+ const integration = getIntegration(parsedParams.data.id);
40
+ if (!integration) {
41
+ return NextResponse.json({ error: "Integration not found" }, { status: 404 });
42
+ }
43
+ const container = await createRequestContainer();
44
+ const credentialsService = container.resolve("integrationCredentialsService");
45
+ const scope = { organizationId: auth.orgId, tenantId: auth.tenantId };
46
+ const values = await credentialsService.resolve(integration.id, scope);
47
+ return NextResponse.json({
48
+ integrationId: integration.id,
49
+ schema: credentialsService.getSchema(integration.id),
50
+ credentials: values ?? {}
51
+ });
52
+ }
53
+ async function PUT(req, ctx) {
54
+ const auth = await getAuthFromRequest(req);
55
+ if (!auth?.tenantId || !auth.orgId) {
56
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
57
+ }
58
+ const rawParams = await resolveParams(ctx);
59
+ const parsedParams = idParamsSchema.safeParse(rawParams);
60
+ if (!parsedParams.success) {
61
+ return NextResponse.json({ error: "Invalid integration id" }, { status: 400 });
62
+ }
63
+ const integration = getIntegration(parsedParams.data.id);
64
+ if (!integration) {
65
+ return NextResponse.json({ error: "Integration not found" }, { status: 404 });
66
+ }
67
+ const payload = await req.json().catch(() => null);
68
+ const parsedBody = saveCredentialsSchema.safeParse(payload);
69
+ if (!parsedBody.success) {
70
+ return NextResponse.json({ error: "Invalid credentials payload", details: parsedBody.error.flatten() }, { status: 422 });
71
+ }
72
+ const container = await createRequestContainer();
73
+ const guardResult = await runIntegrationMutationGuards(
74
+ container,
75
+ {
76
+ tenantId: auth.tenantId,
77
+ organizationId: auth.orgId,
78
+ userId: auth.sub ?? "",
79
+ resourceKind: "integrations.integration",
80
+ resourceId: integration.id,
81
+ operation: "update",
82
+ requestMethod: req.method,
83
+ requestHeaders: req.headers,
84
+ mutationPayload: parsedBody.data
85
+ },
86
+ resolveUserFeatures(auth)
87
+ );
88
+ if (!guardResult.ok) {
89
+ return NextResponse.json(guardResult.errorBody ?? { error: "Operation blocked by guard" }, { status: guardResult.errorStatus ?? 422 });
90
+ }
91
+ let payloadData = parsedBody.data;
92
+ if (guardResult.modifiedPayload) {
93
+ const mergedPayload = { ...parsedBody.data, ...guardResult.modifiedPayload };
94
+ const reparsed = saveCredentialsSchema.safeParse(mergedPayload);
95
+ if (!reparsed.success) {
96
+ return NextResponse.json({ error: "Invalid credentials payload after guard transform", details: reparsed.error.flatten() }, { status: 422 });
97
+ }
98
+ payloadData = reparsed.data;
99
+ }
100
+ const credentialsService = container.resolve("integrationCredentialsService");
101
+ const scope = { organizationId: auth.orgId, tenantId: auth.tenantId };
102
+ await credentialsService.save(integration.id, payloadData.credentials, scope);
103
+ await emitIntegrationsEvent("integrations.credentials.updated", {
104
+ integrationId: integration.id,
105
+ tenantId: auth.tenantId,
106
+ organizationId: auth.orgId,
107
+ userId: auth.sub
108
+ });
109
+ await runIntegrationMutationGuardAfterSuccess(guardResult.afterSuccessCallbacks, {
110
+ tenantId: auth.tenantId,
111
+ organizationId: auth.orgId,
112
+ userId: auth.sub ?? "",
113
+ resourceKind: "integrations.integration",
114
+ resourceId: integration.id,
115
+ operation: "update",
116
+ requestMethod: req.method,
117
+ requestHeaders: req.headers
118
+ });
119
+ return NextResponse.json({ ok: true });
120
+ }
121
+ export {
122
+ GET,
123
+ PUT,
124
+ metadata,
125
+ openApi
126
+ };
127
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../../../src/modules/integrations/api/%5Bid%5D/credentials/route.ts"],
4
+ "sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { getIntegration } from '@open-mercato/shared/modules/integrations/types'\nimport { emitIntegrationsEvent } from '../../../events'\nimport { saveCredentialsSchema } from '../../../data/validators'\nimport type { CredentialsService } from '../../../lib/credentials-service'\nimport {\n resolveUserFeatures,\n runIntegrationMutationGuardAfterSuccess,\n runIntegrationMutationGuards,\n} from '../../guards'\n\nconst idParamsSchema = z.object({ id: z.string().min(1) })\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['integrations.credentials.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['integrations.credentials.manage'] },\n}\n\nexport const openApi = {\n tags: ['Integrations'],\n summary: 'Get or save integration credentials',\n}\n\nfunction resolveParams(ctx: { params?: Promise<{ id?: string }> | { id?: string } }): Promise<{ id?: string } | undefined> | { id?: string } | undefined {\n if (!ctx.params) return undefined\n if (typeof (ctx.params as Promise<unknown>).then === 'function') {\n return ctx.params as Promise<{ id?: string }>\n }\n return ctx.params as { id?: string }\n}\n\nexport async function GET(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const rawParams = await resolveParams(ctx)\n const parsedParams = idParamsSchema.safeParse(rawParams)\n if (!parsedParams.success) {\n return NextResponse.json({ error: 'Invalid integration id' }, { status: 400 })\n }\n\n const integration = getIntegration(parsedParams.data.id)\n if (!integration) {\n return NextResponse.json({ error: 'Integration not found' }, { status: 404 })\n }\n\n const container = await createRequestContainer()\n const credentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }\n\n const values = await credentialsService.resolve(integration.id, scope)\n\n return NextResponse.json({\n integrationId: integration.id,\n schema: credentialsService.getSchema(integration.id),\n credentials: values ?? {},\n })\n}\n\nexport async function PUT(req: Request, ctx: { params?: Promise<{ id?: string }> | { id?: string } }) {\n const auth = await getAuthFromRequest(req)\n if (!auth?.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const rawParams = await resolveParams(ctx)\n const parsedParams = idParamsSchema.safeParse(rawParams)\n if (!parsedParams.success) {\n return NextResponse.json({ error: 'Invalid integration id' }, { status: 400 })\n }\n\n const integration = getIntegration(parsedParams.data.id)\n if (!integration) {\n return NextResponse.json({ error: 'Integration not found' }, { status: 404 })\n }\n\n const payload = await req.json().catch(() => null)\n const parsedBody = saveCredentialsSchema.safeParse(payload)\n if (!parsedBody.success) {\n return NextResponse.json({ error: 'Invalid credentials payload', details: parsedBody.error.flatten() }, { status: 422 })\n }\n\n const container = await createRequestContainer()\n const guardResult = await runIntegrationMutationGuards(\n container,\n {\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n userId: auth.sub ?? '',\n resourceKind: 'integrations.integration',\n resourceId: integration.id,\n operation: 'update',\n requestMethod: req.method,\n requestHeaders: req.headers,\n mutationPayload: parsedBody.data as Record<string, unknown>,\n },\n resolveUserFeatures(auth),\n )\n if (!guardResult.ok) {\n return NextResponse.json(guardResult.errorBody ?? { error: 'Operation blocked by guard' }, { status: guardResult.errorStatus ?? 422 })\n }\n\n let payloadData = parsedBody.data\n if (guardResult.modifiedPayload) {\n const mergedPayload = { ...parsedBody.data, ...guardResult.modifiedPayload }\n const reparsed = saveCredentialsSchema.safeParse(mergedPayload)\n if (!reparsed.success) {\n return NextResponse.json({ error: 'Invalid credentials payload after guard transform', details: reparsed.error.flatten() }, { status: 422 })\n }\n payloadData = reparsed.data\n }\n\n const credentialsService = container.resolve('integrationCredentialsService') as CredentialsService\n const scope = { organizationId: auth.orgId as string, tenantId: auth.tenantId }\n\n await credentialsService.save(integration.id, payloadData.credentials, scope)\n\n await emitIntegrationsEvent('integrations.credentials.updated', {\n integrationId: integration.id,\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n userId: auth.sub,\n })\n\n await runIntegrationMutationGuardAfterSuccess(guardResult.afterSuccessCallbacks, {\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n userId: auth.sub ?? '',\n resourceKind: 'integrations.integration',\n resourceId: integration.id,\n operation: 'update',\n requestMethod: req.method,\n requestHeaders: req.headers,\n })\n\n return NextResponse.json({ ok: true })\n}\n"],
5
+ "mappings": "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",
6
+ "names": []
7
+ }