@open-mercato/core 0.4.6-develop-6d72ec5960 → 0.4.6-develop-cd1e2a9a0e
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.
- package/AGENTS.md +10 -0
- package/dist/generated/entities/integration_credentials/index.js +19 -0
- package/dist/generated/entities/integration_credentials/index.js.map +7 -0
- package/dist/generated/entities/integration_log/index.js +27 -0
- package/dist/generated/entities/integration_log/index.js.map +7 -0
- package/dist/generated/entities/integration_state/index.js +27 -0
- package/dist/generated/entities/integration_state/index.js.map +7 -0
- package/dist/generated/entities/sync_cursor/index.js +19 -0
- package/dist/generated/entities/sync_cursor/index.js.map +7 -0
- package/dist/generated/entities/sync_external_id_mapping/index.js +27 -0
- package/dist/generated/entities/sync_external_id_mapping/index.js.map +7 -0
- package/dist/generated/entities/sync_mapping/index.js +19 -0
- package/dist/generated/entities/sync_mapping/index.js.map +7 -0
- package/dist/generated/entities/sync_run/index.js +45 -0
- package/dist/generated/entities/sync_run/index.js.map +7 -0
- package/dist/generated/entities/sync_schedule/index.js +35 -0
- package/dist/generated/entities/sync_schedule/index.js.map +7 -0
- package/dist/generated/entities.ids.generated.js +14 -0
- package/dist/generated/entities.ids.generated.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +16 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/data_sync/acl.js +11 -0
- package/dist/modules/data_sync/acl.js.map +7 -0
- package/dist/modules/data_sync/api/mappings/[id]/route.js +137 -0
- package/dist/modules/data_sync/api/mappings/[id]/route.js.map +7 -0
- package/dist/modules/data_sync/api/mappings/route.js +132 -0
- package/dist/modules/data_sync/api/mappings/route.js.map +7 -0
- package/dist/modules/data_sync/api/run.js +87 -0
- package/dist/modules/data_sync/api/run.js.map +7 -0
- package/dist/modules/data_sync/api/runs/[id]/cancel.js +49 -0
- package/dist/modules/data_sync/api/runs/[id]/cancel.js.map +7 -0
- package/dist/modules/data_sync/api/runs/[id]/retry.js +93 -0
- package/dist/modules/data_sync/api/runs/[id]/retry.js.map +7 -0
- package/dist/modules/data_sync/api/runs/[id]/route.js +69 -0
- package/dist/modules/data_sync/api/runs/[id]/route.js.map +7 -0
- package/dist/modules/data_sync/api/runs.js +66 -0
- package/dist/modules/data_sync/api/runs.js.map +7 -0
- package/dist/modules/data_sync/api/validate.js +66 -0
- package/dist/modules/data_sync/api/validate.js.map +7 -0
- package/dist/modules/data_sync/backend/data-sync/page.js +216 -0
- package/dist/modules/data_sync/backend/data-sync/page.js.map +7 -0
- package/dist/modules/data_sync/backend/data-sync/page.meta.js +25 -0
- package/dist/modules/data_sync/backend/data-sync/page.meta.js.map +7 -0
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js +178 -0
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.js.map +7 -0
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.meta.js +14 -0
- package/dist/modules/data_sync/backend/data-sync/runs/[id]/page.meta.js.map +7 -0
- package/dist/modules/data_sync/data/entities.js +228 -0
- package/dist/modules/data_sync/data/entities.js.map +7 -0
- package/dist/modules/data_sync/data/validators.js +32 -0
- package/dist/modules/data_sync/data/validators.js.map +7 -0
- package/dist/modules/data_sync/di.js +26 -0
- package/dist/modules/data_sync/di.js.map +7 -0
- package/dist/modules/data_sync/events.js +16 -0
- package/dist/modules/data_sync/events.js.map +7 -0
- package/dist/modules/data_sync/index.js +9 -0
- package/dist/modules/data_sync/index.js.map +7 -0
- package/dist/modules/data_sync/lib/adapter-registry.js +16 -0
- package/dist/modules/data_sync/lib/adapter-registry.js.map +7 -0
- package/dist/modules/data_sync/lib/adapter.js +1 -0
- package/dist/modules/data_sync/lib/adapter.js.map +7 -0
- package/dist/modules/data_sync/lib/id-mapping.js +79 -0
- package/dist/modules/data_sync/lib/id-mapping.js.map +7 -0
- package/dist/modules/data_sync/lib/queue.js +17 -0
- package/dist/modules/data_sync/lib/queue.js.map +7 -0
- package/dist/modules/data_sync/lib/sync-engine.js +309 -0
- package/dist/modules/data_sync/lib/sync-engine.js.map +7 -0
- package/dist/modules/data_sync/lib/sync-run-service.js +148 -0
- package/dist/modules/data_sync/lib/sync-run-service.js.map +7 -0
- package/dist/modules/data_sync/migrations/Migration20260304113737.js +17 -0
- package/dist/modules/data_sync/migrations/Migration20260304113737.js.map +7 -0
- package/dist/modules/data_sync/setup.js +13 -0
- package/dist/modules/data_sync/setup.js.map +7 -0
- package/dist/modules/data_sync/workers/sync-export.js +14 -0
- package/dist/modules/data_sync/workers/sync-export.js.map +7 -0
- package/dist/modules/data_sync/workers/sync-import.js +14 -0
- package/dist/modules/data_sync/workers/sync-import.js.map +7 -0
- package/dist/modules/data_sync/workers/sync-scheduled.js +63 -0
- package/dist/modules/data_sync/workers/sync-scheduled.js.map +7 -0
- package/dist/modules/entities/lib/encryptionDefaults.js +4 -0
- package/dist/modules/entities/lib/encryptionDefaults.js.map +2 -2
- package/dist/modules/integrations/acl.js +4 -1
- package/dist/modules/integrations/acl.js.map +2 -2
- package/dist/modules/integrations/api/[id]/credentials/route.js +127 -0
- package/dist/modules/integrations/api/[id]/credentials/route.js.map +7 -0
- package/dist/modules/integrations/api/[id]/health/route.js +46 -0
- package/dist/modules/integrations/api/[id]/health/route.js.map +7 -0
- package/dist/modules/integrations/api/[id]/route.js +65 -0
- package/dist/modules/integrations/api/[id]/route.js.map +7 -0
- package/dist/modules/integrations/api/[id]/state/route.js +109 -0
- package/dist/modules/integrations/api/[id]/state/route.js.map +7 -0
- package/dist/modules/integrations/api/[id]/version/route.js +117 -0
- package/dist/modules/integrations/api/[id]/version/route.js.map +7 -0
- package/dist/modules/integrations/api/guards.js +31 -0
- package/dist/modules/integrations/api/guards.js.map +7 -0
- package/dist/modules/integrations/api/logs/route.js +60 -0
- package/dist/modules/integrations/api/logs/route.js.map +7 -0
- package/dist/modules/integrations/api/openapi.js +25 -0
- package/dist/modules/integrations/api/openapi.js.map +7 -0
- package/dist/modules/integrations/api/route.js +68 -0
- package/dist/modules/integrations/api/route.js.map +7 -0
- package/dist/modules/integrations/backend/integrations/[id]/page.js +313 -0
- package/dist/modules/integrations/backend/integrations/[id]/page.js.map +7 -0
- package/dist/modules/integrations/backend/integrations/[id]/page.meta.js +15 -0
- package/dist/modules/integrations/backend/integrations/[id]/page.meta.js.map +7 -0
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js +189 -0
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.js.map +7 -0
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.meta.js +15 -0
- package/dist/modules/integrations/backend/integrations/bundle/[id]/page.meta.js.map +7 -0
- package/dist/modules/integrations/backend/integrations/page.js +212 -0
- package/dist/modules/integrations/backend/integrations/page.js.map +7 -0
- package/dist/modules/integrations/backend/integrations/page.meta.js +22 -0
- package/dist/modules/integrations/backend/integrations/page.meta.js.map +7 -0
- package/dist/modules/integrations/data/enrichers.js +27 -12
- package/dist/modules/integrations/data/enrichers.js.map +2 -2
- package/dist/modules/integrations/data/entities.js +136 -1
- package/dist/modules/integrations/data/entities.js.map +2 -2
- package/dist/modules/integrations/data/validators.js +36 -0
- package/dist/modules/integrations/data/validators.js.map +7 -0
- package/dist/modules/integrations/di.js +24 -0
- package/dist/modules/integrations/di.js.map +7 -0
- package/dist/modules/integrations/events.js +19 -0
- package/dist/modules/integrations/events.js.map +7 -0
- package/dist/modules/integrations/lib/credentials-service.js +159 -0
- package/dist/modules/integrations/lib/credentials-service.js.map +7 -0
- package/dist/modules/integrations/lib/health-service.js +37 -0
- package/dist/modules/integrations/lib/health-service.js.map +7 -0
- package/dist/modules/integrations/lib/log-service.js +66 -0
- package/dist/modules/integrations/lib/log-service.js.map +7 -0
- package/dist/modules/integrations/lib/registry-service.js +33 -0
- package/dist/modules/integrations/lib/registry-service.js.map +7 -0
- package/dist/modules/integrations/lib/state-service.js +55 -0
- package/dist/modules/integrations/lib/state-service.js.map +7 -0
- package/dist/modules/integrations/lib/types.js +1 -0
- package/dist/modules/integrations/lib/types.js.map +7 -0
- package/dist/modules/integrations/migrations/Migration20260304113737.js +19 -0
- package/dist/modules/integrations/migrations/Migration20260304113737.js.map +7 -0
- package/dist/modules/integrations/setup.js +2 -2
- package/dist/modules/integrations/setup.js.map +2 -2
- package/dist/modules/integrations/widgets/injection-table.js.map +1 -1
- package/dist/modules/integrations/workers/log-pruner.js +18 -0
- package/dist/modules/integrations/workers/log-pruner.js.map +7 -0
- package/generated/entities/integration_credentials/index.ts +8 -0
- package/generated/entities/integration_log/index.ts +12 -0
- package/generated/entities/integration_state/index.ts +12 -0
- package/generated/entities/sync_cursor/index.ts +8 -0
- package/generated/entities/sync_external_id_mapping/index.ts +12 -0
- package/generated/entities/sync_mapping/index.ts +8 -0
- package/generated/entities/sync_run/index.ts +21 -0
- package/generated/entities/sync_schedule/index.ts +16 -0
- package/generated/entities.ids.generated.ts +14 -0
- package/generated/entity-fields-registry.ts +16 -0
- package/package.json +2 -2
- package/src/modules/data_sync/AGENTS.md +157 -0
- package/src/modules/data_sync/acl.ts +7 -0
- package/src/modules/data_sync/api/mappings/[id]/route.ts +158 -0
- package/src/modules/data_sync/api/mappings/route.ts +144 -0
- package/src/modules/data_sync/api/run.ts +97 -0
- package/src/modules/data_sync/api/runs/[id]/cancel.ts +57 -0
- package/src/modules/data_sync/api/runs/[id]/retry.ts +108 -0
- package/src/modules/data_sync/api/runs/[id]/route.ts +81 -0
- package/src/modules/data_sync/api/runs.ts +69 -0
- package/src/modules/data_sync/api/validate.ts +73 -0
- package/src/modules/data_sync/backend/data-sync/page.meta.ts +21 -0
- package/src/modules/data_sync/backend/data-sync/page.tsx +244 -0
- package/src/modules/data_sync/backend/data-sync/runs/[id]/page.meta.ts +10 -0
- package/src/modules/data_sync/backend/data-sync/runs/[id]/page.tsx +278 -0
- package/src/modules/data_sync/data/entities.ts +180 -0
- package/src/modules/data_sync/data/validators.ts +35 -0
- package/src/modules/data_sync/di.ts +38 -0
- package/src/modules/data_sync/events.ts +12 -0
- package/src/modules/data_sync/i18n/de.json +48 -0
- package/src/modules/data_sync/i18n/en.json +48 -0
- package/src/modules/data_sync/i18n/es.json +48 -0
- package/src/modules/data_sync/i18n/pl.json +48 -0
- package/src/modules/data_sync/index.ts +5 -0
- package/src/modules/data_sync/lib/adapter-registry.ts +15 -0
- package/src/modules/data_sync/lib/adapter.ts +90 -0
- package/src/modules/data_sync/lib/id-mapping.ts +95 -0
- package/src/modules/data_sync/lib/queue.ts +19 -0
- package/src/modules/data_sync/lib/sync-engine.ts +375 -0
- package/src/modules/data_sync/lib/sync-run-service.ts +187 -0
- package/src/modules/data_sync/migrations/.snapshot-open-mercato.json +653 -0
- package/src/modules/data_sync/migrations/Migration20260304113737.ts +19 -0
- package/src/modules/data_sync/setup.ts +11 -0
- package/src/modules/data_sync/workers/sync-export.ts +27 -0
- package/src/modules/data_sync/workers/sync-import.ts +27 -0
- package/src/modules/data_sync/workers/sync-scheduled.ts +84 -0
- package/src/modules/entities/lib/encryptionDefaults.ts +4 -0
- package/src/modules/integrations/AGENTS.md +160 -0
- package/src/modules/integrations/acl.ts +3 -0
- package/src/modules/integrations/api/[id]/credentials/route.ts +142 -0
- package/src/modules/integrations/api/[id]/health/route.ts +53 -0
- package/src/modules/integrations/api/[id]/route.ts +76 -0
- package/src/modules/integrations/api/[id]/state/route.ts +121 -0
- package/src/modules/integrations/api/[id]/version/route.ts +132 -0
- package/src/modules/integrations/api/guards.ts +59 -0
- package/src/modules/integrations/api/logs/route.ts +63 -0
- package/src/modules/integrations/api/openapi.ts +22 -0
- package/src/modules/integrations/api/route.ts +73 -0
- package/src/modules/integrations/backend/integrations/[id]/page.meta.ts +11 -0
- package/src/modules/integrations/backend/integrations/[id]/page.tsx +424 -0
- package/src/modules/integrations/backend/integrations/bundle/[id]/page.meta.ts +11 -0
- package/src/modules/integrations/backend/integrations/bundle/[id]/page.tsx +249 -0
- package/src/modules/integrations/backend/integrations/page.meta.ts +18 -0
- package/src/modules/integrations/backend/integrations/page.tsx +296 -0
- package/src/modules/integrations/data/enrichers.ts +35 -18
- package/src/modules/integrations/data/entities.ts +114 -5
- package/src/modules/integrations/data/validators.ts +41 -0
- package/src/modules/integrations/di.ts +31 -0
- package/src/modules/integrations/events.ts +17 -0
- package/src/modules/integrations/i18n/de.json +70 -0
- package/src/modules/integrations/i18n/en.json +70 -0
- package/src/modules/integrations/i18n/es.json +70 -0
- package/src/modules/integrations/i18n/pl.json +70 -0
- package/src/modules/integrations/lib/credentials-service.ts +204 -0
- package/src/modules/integrations/lib/health-service.ts +59 -0
- package/src/modules/integrations/lib/log-service.ts +84 -0
- package/src/modules/integrations/lib/registry-service.ts +42 -0
- package/src/modules/integrations/lib/state-service.ts +64 -0
- package/src/modules/integrations/lib/types.ts +4 -0
- package/src/modules/integrations/migrations/.snapshot-open-mercato.json +582 -0
- package/src/modules/integrations/migrations/Migration20260304113737.ts +21 -0
- package/src/modules/integrations/setup.ts +2 -2
- package/src/modules/integrations/widgets/injection-table.ts +1 -1
- package/src/modules/integrations/workers/log-pruner.ts +30 -0
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/integrations/data/entities.ts"],
|
|
4
|
-
"sourcesContent": ["import { Entity, PrimaryKey, Property, Index } from '@mikro-orm/core'\n\n
|
|
5
|
-
"mappings": ";;;;;;;;;;AAAA,SAAS,QAAQ,YAAY,UAAU,
|
|
4
|
+
"sourcesContent": ["import { Entity, PrimaryKey, Property, Index, OptionalProps } from '@mikro-orm/core'\n\n@Entity({ tableName: 'sync_external_id_mappings' })\n@Index({ properties: ['internalEntityType', 'internalEntityId', 'organizationId'] })\n@Index({ properties: ['integrationId', 'externalId', 'organizationId'] })\nexport class SyncExternalIdMapping {\n [OptionalProps]?: 'syncStatus' | 'lastSyncedAt' | 'createdAt' | 'updatedAt' | 'deletedAt'\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\n@Entity({ tableName: 'integration_credentials' })\n@Index({ properties: ['integrationId', 'organizationId', 'tenantId'] })\nexport class IntegrationCredentials {\n [OptionalProps]?: 'createdAt' | 'updatedAt' | 'deletedAt'\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: 'credentials', type: 'json' })\n credentials!: Record<string, unknown>\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\n@Entity({ tableName: 'integration_states' })\n@Index({ properties: ['integrationId', 'organizationId', 'tenantId'] })\nexport class IntegrationState {\n [OptionalProps]?: 'isEnabled' | 'apiVersion' | 'reauthRequired' | 'lastHealthStatus' | 'lastHealthCheckedAt' | 'createdAt' | 'updatedAt' | 'deletedAt'\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: 'is_enabled', type: 'boolean', default: true })\n isEnabled: boolean = true\n\n @Property({ name: 'api_version', type: 'text', nullable: true })\n apiVersion?: string | null\n\n @Property({ name: 'reauth_required', type: 'boolean', default: false })\n reauthRequired: boolean = false\n\n @Property({ name: 'last_health_status', type: 'text', nullable: true })\n lastHealthStatus?: 'healthy' | 'degraded' | 'unhealthy' | null\n\n @Property({ name: 'last_health_checked_at', type: Date, nullable: true })\n lastHealthCheckedAt?: 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\n@Entity({ tableName: 'integration_logs' })\n@Index({ properties: ['integrationId', 'organizationId', 'tenantId', 'createdAt'] })\n@Index({ properties: ['level', 'organizationId', 'tenantId', 'createdAt'] })\nexport class IntegrationLog {\n [OptionalProps]?: 'runId' | 'scopeEntityType' | 'scopeEntityId' | 'code' | 'payload' | 'createdAt'\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: 'run_id', type: 'uuid', nullable: true })\n runId?: string | null\n\n @Property({ name: 'scope_entity_type', type: 'text', nullable: true })\n scopeEntityType?: string | null\n\n @Property({ name: 'scope_entity_id', type: 'uuid', nullable: true })\n scopeEntityId?: string | null\n\n @Property({ name: 'level', type: 'text' })\n level!: 'info' | 'warn' | 'error'\n\n @Property({ name: 'message', type: 'text' })\n message!: string\n\n @Property({ name: 'code', type: 'text', nullable: true })\n code?: string | null\n\n @Property({ name: 'payload', type: 'json', nullable: true })\n payload?: Record<string, unknown> | 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"],
|
|
5
|
+
"mappings": ";;;;;;;;;;AAAA,SAAS,QAAQ,YAAY,UAAU,OAAO,qBAAqB;AAMhE;AADI,IAAM,wBAAN,MAA4B;AAAA,EAA5B;AAkBL,sBAA4D;AAY5D,qBAAkB,oBAAI,KAAK;AAG3B,qBAAkB,oBAAI,KAAK;AAAA;AAI7B;AAlCE;AAAA,EADC,WAAW,EAAE,MAAM,QAAQ,YAAY,oBAAoB,CAAC;AAAA,GAFlD,sBAGX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,kBAAkB,MAAM,OAAO,CAAC;AAAA,GALvC,sBAMX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,wBAAwB,MAAM,OAAO,CAAC;AAAA,GAR7C,sBASX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,sBAAsB,MAAM,OAAO,CAAC;AAAA,GAX3C,sBAYX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,eAAe,MAAM,OAAO,CAAC;AAAA,GAdpC,sBAeX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,eAAe,MAAM,QAAQ,SAAS,aAAa,CAAC;AAAA,GAjB3D,sBAkBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,kBAAkB,MAAM,MAAM,UAAU,KAAK,CAAC;AAAA,GApBrD,sBAqBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,mBAAmB,MAAM,OAAO,CAAC;AAAA,GAvBxC,sBAwBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,aAAa,MAAM,OAAO,CAAC;AAAA,GA1BlC,sBA2BX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,MAAM,oBAAI,KAAK,EAAE,CAAC;AAAA,GA7B7D,sBA8BX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,MAAM,oBAAI,KAAK,EAAE,CAAC;AAAA,GAhC7D,sBAiCX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,KAAK,CAAC;AAAA,GAnCjD,sBAoCX;AApCW,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;AA0CV;AADI,IAAM,yBAAN,MAA6B;AAAA,EAA7B;AAkBL,qBAAkB,oBAAI,KAAK;AAG3B,qBAAkB,oBAAI,KAAK;AAAA;AAI7B;AAtBE;AAAA,EADC,WAAW,EAAE,MAAM,QAAQ,YAAY,oBAAoB,CAAC;AAAA,GAFlD,uBAGX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,kBAAkB,MAAM,OAAO,CAAC;AAAA,GALvC,uBAMX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,eAAe,MAAM,OAAO,CAAC;AAAA,GARpC,uBASX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,mBAAmB,MAAM,OAAO,CAAC;AAAA,GAXxC,uBAYX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,aAAa,MAAM,OAAO,CAAC;AAAA,GAdlC,uBAeX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,MAAM,oBAAI,KAAK,EAAE,CAAC;AAAA,GAjB7D,uBAkBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,MAAM,oBAAI,KAAK,EAAE,CAAC;AAAA,GApB7D,uBAqBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,KAAK,CAAC;AAAA,GAvBjD,uBAwBX;AAxBW,yBAAN;AAAA,EAFN,OAAO,EAAE,WAAW,0BAA0B,CAAC;AAAA,EAC/C,MAAM,EAAE,YAAY,CAAC,iBAAiB,kBAAkB,UAAU,EAAE,CAAC;AAAA,GACzD;AA8BV;AADI,IAAM,mBAAN,MAAuB;AAAA,EAAvB;AASL,qBAAqB;AAMrB,0BAA0B;AAe1B,qBAAkB,oBAAI,KAAK;AAG3B,qBAAkB,oBAAI,KAAK;AAAA;AAI7B;AAlCE;AAAA,EADC,WAAW,EAAE,MAAM,QAAQ,YAAY,oBAAoB,CAAC;AAAA,GAFlD,iBAGX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,kBAAkB,MAAM,OAAO,CAAC;AAAA,GALvC,iBAMX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,WAAW,SAAS,KAAK,CAAC;AAAA,GARrD,iBASX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,eAAe,MAAM,QAAQ,UAAU,KAAK,CAAC;AAAA,GAXpD,iBAYX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,mBAAmB,MAAM,WAAW,SAAS,MAAM,CAAC;AAAA,GAd3D,iBAeX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,sBAAsB,MAAM,QAAQ,UAAU,KAAK,CAAC;AAAA,GAjB3D,iBAkBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,0BAA0B,MAAM,MAAM,UAAU,KAAK,CAAC;AAAA,GApB7D,iBAqBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,mBAAmB,MAAM,OAAO,CAAC;AAAA,GAvBxC,iBAwBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,aAAa,MAAM,OAAO,CAAC;AAAA,GA1BlC,iBA2BX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,MAAM,oBAAI,KAAK,EAAE,CAAC;AAAA,GA7B7D,iBA8BX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,MAAM,oBAAI,KAAK,EAAE,CAAC;AAAA,GAhC7D,iBAiCX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,KAAK,CAAC;AAAA,GAnCjD,iBAoCX;AApCW,mBAAN;AAAA,EAFN,OAAO,EAAE,WAAW,qBAAqB,CAAC;AAAA,EAC1C,MAAM,EAAE,YAAY,CAAC,iBAAiB,kBAAkB,UAAU,EAAE,CAAC;AAAA,GACzD;AA2CV;AADI,IAAM,iBAAN,MAAqB;AAAA,EAArB;AAoCL,qBAAkB,oBAAI,KAAK;AAAA;AAC7B;AAlCE;AAAA,EADC,WAAW,EAAE,MAAM,QAAQ,YAAY,oBAAoB,CAAC;AAAA,GAFlD,eAGX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,kBAAkB,MAAM,OAAO,CAAC;AAAA,GALvC,eAMX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,UAAU,MAAM,QAAQ,UAAU,KAAK,CAAC;AAAA,GAR/C,eASX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,qBAAqB,MAAM,QAAQ,UAAU,KAAK,CAAC;AAAA,GAX1D,eAYX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,mBAAmB,MAAM,QAAQ,UAAU,KAAK,CAAC;AAAA,GAdxD,eAeX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,SAAS,MAAM,OAAO,CAAC;AAAA,GAjB9B,eAkBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,WAAW,MAAM,OAAO,CAAC;AAAA,GApBhC,eAqBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,QAAQ,MAAM,QAAQ,UAAU,KAAK,CAAC;AAAA,GAvB7C,eAwBX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,WAAW,MAAM,QAAQ,UAAU,KAAK,CAAC;AAAA,GA1BhD,eA2BX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,mBAAmB,MAAM,OAAO,CAAC;AAAA,GA7BxC,eA8BX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,aAAa,MAAM,OAAO,CAAC;AAAA,GAhClC,eAiCX;AAGA;AAAA,EADC,SAAS,EAAE,MAAM,cAAc,MAAM,MAAM,UAAU,MAAM,oBAAI,KAAK,EAAE,CAAC;AAAA,GAnC7D,eAoCX;AApCW,iBAAN;AAAA,EAHN,OAAO,EAAE,WAAW,mBAAmB,CAAC;AAAA,EACxC,MAAM,EAAE,YAAY,CAAC,iBAAiB,kBAAkB,YAAY,WAAW,EAAE,CAAC;AAAA,EAClF,MAAM,EAAE,YAAY,CAAC,SAAS,kBAAkB,YAAY,WAAW,EAAE,CAAC;AAAA,GAC9D;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
const saveCredentialsSchema = z.object({
|
|
3
|
+
credentials: z.record(
|
|
4
|
+
z.string().min(1).max(128),
|
|
5
|
+
z.union([z.string().max(2e4), z.number(), z.boolean(), z.null()])
|
|
6
|
+
)
|
|
7
|
+
}).refine((value) => Object.keys(value.credentials).length <= 200, {
|
|
8
|
+
message: "At most 200 credential fields are allowed"
|
|
9
|
+
});
|
|
10
|
+
const updateVersionSchema = z.object({
|
|
11
|
+
apiVersion: z.string().min(1)
|
|
12
|
+
});
|
|
13
|
+
const updateStateSchema = z.object({
|
|
14
|
+
isEnabled: z.boolean().optional(),
|
|
15
|
+
reauthRequired: z.boolean().optional()
|
|
16
|
+
}).refine((value) => value.isEnabled !== void 0 || value.reauthRequired !== void 0, {
|
|
17
|
+
message: "At least one state field must be provided"
|
|
18
|
+
});
|
|
19
|
+
const integrationLogLevelSchema = z.enum(["info", "warn", "error"]);
|
|
20
|
+
const listIntegrationLogsQuerySchema = z.object({
|
|
21
|
+
integrationId: z.string().min(1).optional(),
|
|
22
|
+
level: integrationLogLevelSchema.optional(),
|
|
23
|
+
runId: z.string().uuid().optional(),
|
|
24
|
+
entityType: z.string().optional(),
|
|
25
|
+
entityId: z.string().uuid().optional(),
|
|
26
|
+
page: z.coerce.number().int().min(1).default(1),
|
|
27
|
+
pageSize: z.coerce.number().int().min(1).max(100).default(20)
|
|
28
|
+
});
|
|
29
|
+
export {
|
|
30
|
+
integrationLogLevelSchema,
|
|
31
|
+
listIntegrationLogsQuerySchema,
|
|
32
|
+
saveCredentialsSchema,
|
|
33
|
+
updateStateSchema,
|
|
34
|
+
updateVersionSchema
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=validators.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/integrations/data/validators.ts"],
|
|
4
|
+
"sourcesContent": ["import { z } from 'zod'\n\nexport const saveCredentialsSchema = z.object({\n credentials: z.record(\n z.string().min(1).max(128),\n z.union([z.string().max(20_000), z.number(), z.boolean(), z.null()]),\n ),\n}).refine((value) => Object.keys(value.credentials).length <= 200, {\n message: 'At most 200 credential fields are allowed',\n})\n\nexport type SaveCredentialsInput = z.infer<typeof saveCredentialsSchema>\n\nexport const updateVersionSchema = z.object({\n apiVersion: z.string().min(1),\n})\n\nexport type UpdateVersionInput = z.infer<typeof updateVersionSchema>\n\nexport const updateStateSchema = z.object({\n isEnabled: z.boolean().optional(),\n reauthRequired: z.boolean().optional(),\n}).refine((value) => value.isEnabled !== undefined || value.reauthRequired !== undefined, {\n message: 'At least one state field must be provided',\n})\n\nexport type UpdateStateInput = z.infer<typeof updateStateSchema>\n\nexport const integrationLogLevelSchema = z.enum(['info', 'warn', 'error'])\n\nexport const listIntegrationLogsQuerySchema = z.object({\n integrationId: z.string().min(1).optional(),\n level: integrationLogLevelSchema.optional(),\n runId: z.string().uuid().optional(),\n entityType: z.string().optional(),\n entityId: z.string().uuid().optional(),\n page: z.coerce.number().int().min(1).default(1),\n pageSize: z.coerce.number().int().min(1).max(100).default(20),\n})\n\nexport type ListIntegrationLogsQuery = z.infer<typeof listIntegrationLogsQuerySchema>\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,SAAS;AAEX,MAAM,wBAAwB,EAAE,OAAO;AAAA,EAC5C,aAAa,EAAE;AAAA,IACb,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG;AAAA,IACzB,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,IAAI,GAAM,GAAG,EAAE,OAAO,GAAG,EAAE,QAAQ,GAAG,EAAE,KAAK,CAAC,CAAC;AAAA,EACrE;AACF,CAAC,EAAE,OAAO,CAAC,UAAU,OAAO,KAAK,MAAM,WAAW,EAAE,UAAU,KAAK;AAAA,EACjE,SAAS;AACX,CAAC;AAIM,MAAM,sBAAsB,EAAE,OAAO;AAAA,EAC1C,YAAY,EAAE,OAAO,EAAE,IAAI,CAAC;AAC9B,CAAC;AAIM,MAAM,oBAAoB,EAAE,OAAO;AAAA,EACxC,WAAW,EAAE,QAAQ,EAAE,SAAS;AAAA,EAChC,gBAAgB,EAAE,QAAQ,EAAE,SAAS;AACvC,CAAC,EAAE,OAAO,CAAC,UAAU,MAAM,cAAc,UAAa,MAAM,mBAAmB,QAAW;AAAA,EACxF,SAAS;AACX,CAAC;AAIM,MAAM,4BAA4B,EAAE,KAAK,CAAC,QAAQ,QAAQ,OAAO,CAAC;AAElE,MAAM,iCAAiC,EAAE,OAAO;AAAA,EACrD,eAAe,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,SAAS;AAAA,EAC1C,OAAO,0BAA0B,SAAS;AAAA,EAC1C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA,EAClC,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,EAChC,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS;AAAA,EACrC,MAAM,EAAE,OAAO,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,QAAQ,CAAC;AAAA,EAC9C,UAAU,EAAE,OAAO,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,IAAI,GAAG,EAAE,QAAQ,EAAE;AAC9D,CAAC;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { asFunction, asValue } from "awilix";
|
|
2
|
+
import { IntegrationCredentials, IntegrationLog, IntegrationState, SyncExternalIdMapping } from "./data/entities.js";
|
|
3
|
+
import { createCredentialsService } from "./lib/credentials-service.js";
|
|
4
|
+
import { createIntegrationStateService } from "./lib/state-service.js";
|
|
5
|
+
import { createIntegrationLogService } from "./lib/log-service.js";
|
|
6
|
+
import { createHealthService } from "./lib/health-service.js";
|
|
7
|
+
function register(container) {
|
|
8
|
+
container.register({
|
|
9
|
+
integrationCredentialsService: asFunction(({ em }) => createCredentialsService(em)).scoped().proxy(),
|
|
10
|
+
integrationStateService: asFunction(({ em }) => createIntegrationStateService(em)).scoped().proxy(),
|
|
11
|
+
integrationLogService: asFunction(({ em }) => createIntegrationLogService(em)).scoped().proxy(),
|
|
12
|
+
integrationHealthService: asFunction(
|
|
13
|
+
({ integrationStateService, integrationLogService }) => createHealthService(container, integrationStateService, integrationLogService)
|
|
14
|
+
).scoped().proxy(),
|
|
15
|
+
SyncExternalIdMapping: asValue(SyncExternalIdMapping),
|
|
16
|
+
IntegrationCredentials: asValue(IntegrationCredentials),
|
|
17
|
+
IntegrationState: asValue(IntegrationState),
|
|
18
|
+
IntegrationLog: asValue(IntegrationLog)
|
|
19
|
+
});
|
|
20
|
+
}
|
|
21
|
+
export {
|
|
22
|
+
register
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=di.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/modules/integrations/di.ts"],
|
|
4
|
+
"sourcesContent": ["import { asFunction, asValue } from 'awilix'\nimport type { AppContainer } from '@open-mercato/shared/lib/di/container'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { IntegrationCredentials, IntegrationLog, IntegrationState, SyncExternalIdMapping } from './data/entities'\nimport { createCredentialsService } from './lib/credentials-service'\nimport { createIntegrationStateService } from './lib/state-service'\nimport { createIntegrationLogService } from './lib/log-service'\nimport { createHealthService } from './lib/health-service'\nimport type { IntegrationStateService } from './lib/state-service'\nimport type { IntegrationLogService } from './lib/log-service'\n\ntype Cradle = {\n em: EntityManager\n integrationStateService: IntegrationStateService\n integrationLogService: IntegrationLogService\n}\n\nexport function register(container: AppContainer) {\n container.register({\n integrationCredentialsService: asFunction(({ em }: Cradle) => createCredentialsService(em)).scoped().proxy(),\n integrationStateService: asFunction(({ em }: Cradle) => createIntegrationStateService(em)).scoped().proxy(),\n integrationLogService: asFunction(({ em }: Cradle) => createIntegrationLogService(em)).scoped().proxy(),\n integrationHealthService: asFunction(({ integrationStateService, integrationLogService }: Cradle) =>\n createHealthService(container, integrationStateService, integrationLogService),\n ).scoped().proxy(),\n SyncExternalIdMapping: asValue(SyncExternalIdMapping),\n IntegrationCredentials: asValue(IntegrationCredentials),\n IntegrationState: asValue(IntegrationState),\n IntegrationLog: asValue(IntegrationLog),\n })\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,YAAY,eAAe;AAGpC,SAAS,wBAAwB,gBAAgB,kBAAkB,6BAA6B;AAChG,SAAS,gCAAgC;AACzC,SAAS,qCAAqC;AAC9C,SAAS,mCAAmC;AAC5C,SAAS,2BAA2B;AAU7B,SAAS,SAAS,WAAyB;AAChD,YAAU,SAAS;AAAA,IACjB,+BAA+B,WAAW,CAAC,EAAE,GAAG,MAAc,yBAAyB,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM;AAAA,IAC3G,yBAAyB,WAAW,CAAC,EAAE,GAAG,MAAc,8BAA8B,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM;AAAA,IAC1G,uBAAuB,WAAW,CAAC,EAAE,GAAG,MAAc,4BAA4B,EAAE,CAAC,EAAE,OAAO,EAAE,MAAM;AAAA,IACtG,0BAA0B;AAAA,MAAW,CAAC,EAAE,yBAAyB,sBAAsB,MACrF,oBAAoB,WAAW,yBAAyB,qBAAqB;AAAA,IAC/E,EAAE,OAAO,EAAE,MAAM;AAAA,IACjB,uBAAuB,QAAQ,qBAAqB;AAAA,IACpD,wBAAwB,QAAQ,sBAAsB;AAAA,IACtD,kBAAkB,QAAQ,gBAAgB;AAAA,IAC1C,gBAAgB,QAAQ,cAAc;AAAA,EACxC,CAAC;AACH;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { createModuleEvents } from "@open-mercato/shared/modules/events";
|
|
2
|
+
const events = [
|
|
3
|
+
{ id: "integrations.credentials.updated", label: "Integration Credentials Updated", category: "custom", entity: "credentials" },
|
|
4
|
+
{ id: "integrations.state.updated", label: "Integration State Updated", category: "custom", entity: "state" },
|
|
5
|
+
{ id: "integrations.version.changed", label: "Integration Version Changed", category: "custom", entity: "state" },
|
|
6
|
+
{ id: "integrations.log.created", label: "Integration Log Created", category: "system", entity: "log", excludeFromTriggers: true }
|
|
7
|
+
];
|
|
8
|
+
const eventsConfig = createModuleEvents({
|
|
9
|
+
moduleId: "integrations",
|
|
10
|
+
events
|
|
11
|
+
});
|
|
12
|
+
const emitIntegrationsEvent = eventsConfig.emit;
|
|
13
|
+
var events_default = eventsConfig;
|
|
14
|
+
export {
|
|
15
|
+
events_default as default,
|
|
16
|
+
emitIntegrationsEvent,
|
|
17
|
+
eventsConfig
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=events.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/modules/integrations/events.ts"],
|
|
4
|
+
"sourcesContent": ["import { createModuleEvents } from '@open-mercato/shared/modules/events'\n\nconst events = [\n { id: 'integrations.credentials.updated', label: 'Integration Credentials Updated', category: 'custom', entity: 'credentials' },\n { id: 'integrations.state.updated', label: 'Integration State Updated', category: 'custom', entity: 'state' },\n { id: 'integrations.version.changed', label: 'Integration Version Changed', category: 'custom', entity: 'state' },\n { id: 'integrations.log.created', label: 'Integration Log Created', category: 'system', entity: 'log', excludeFromTriggers: true },\n] as const\n\nexport const eventsConfig = createModuleEvents({\n moduleId: 'integrations',\n events,\n})\n\nexport const emitIntegrationsEvent = eventsConfig.emit\n\nexport default eventsConfig\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,0BAA0B;AAEnC,MAAM,SAAS;AAAA,EACb,EAAE,IAAI,oCAAoC,OAAO,mCAAmC,UAAU,UAAU,QAAQ,cAAc;AAAA,EAC9H,EAAE,IAAI,8BAA8B,OAAO,6BAA6B,UAAU,UAAU,QAAQ,QAAQ;AAAA,EAC5G,EAAE,IAAI,gCAAgC,OAAO,+BAA+B,UAAU,UAAU,QAAQ,QAAQ;AAAA,EAChH,EAAE,IAAI,4BAA4B,OAAO,2BAA2B,UAAU,UAAU,QAAQ,OAAO,qBAAqB,KAAK;AACnI;AAEO,MAAM,eAAe,mBAAmB;AAAA,EAC7C,UAAU;AAAA,EACV;AACF,CAAC;AAEM,MAAM,wBAAwB,aAAa;AAElD,IAAO,iBAAQ;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import crypto from "node:crypto";
|
|
2
|
+
import { decryptWithAesGcm, encryptWithAesGcm } from "@open-mercato/shared/lib/encryption/aes";
|
|
3
|
+
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
4
|
+
import { createKmsService } from "@open-mercato/shared/lib/encryption/kms";
|
|
5
|
+
import { getBundle, getIntegration, resolveIntegrationCredentialsSchema } from "@open-mercato/shared/modules/integrations/types";
|
|
6
|
+
import { EncryptionMap } from "../../entities/data/entities.js";
|
|
7
|
+
import { IntegrationCredentials } from "../data/entities.js";
|
|
8
|
+
const ENCRYPTED_CREDENTIALS_BLOB_KEY = "__om_encrypted_credentials_blob_v1";
|
|
9
|
+
const DERIVED_KEY_CONTEXT = "integrations.credentials";
|
|
10
|
+
function resolveFallbackEncryptionSecret() {
|
|
11
|
+
const candidates = [
|
|
12
|
+
process.env.TENANT_DATA_ENCRYPTION_FALLBACK_KEY,
|
|
13
|
+
process.env.TENANT_DATA_ENCRYPTION_KEY,
|
|
14
|
+
process.env.AUTH_SECRET,
|
|
15
|
+
process.env.NEXTAUTH_SECRET
|
|
16
|
+
];
|
|
17
|
+
for (const value of candidates) {
|
|
18
|
+
const normalized = value?.trim();
|
|
19
|
+
if (normalized) return normalized;
|
|
20
|
+
}
|
|
21
|
+
if (process.env.NODE_ENV !== "production") return "om-dev-tenant-encryption";
|
|
22
|
+
console.warn(
|
|
23
|
+
"[integrations.credentials] No encryption secret configured; using emergency fallback secret. Configure TENANT_DATA_ENCRYPTION_FALLBACK_KEY immediately."
|
|
24
|
+
);
|
|
25
|
+
return "om-emergency-fallback-rotate-me";
|
|
26
|
+
}
|
|
27
|
+
function deriveDekFromSecret(secret, tenantId) {
|
|
28
|
+
return crypto.createHash("sha256").update(`${DERIVED_KEY_CONTEXT}:${tenantId}:${secret}`).digest().toString("base64");
|
|
29
|
+
}
|
|
30
|
+
function createCredentialsService(em) {
|
|
31
|
+
const credentialsEncryptionSpec = [{ field: "credentials" }];
|
|
32
|
+
async function ensureCredentialsEncryptionMap(scope) {
|
|
33
|
+
const existing = await findOneWithDecryption(
|
|
34
|
+
em,
|
|
35
|
+
EncryptionMap,
|
|
36
|
+
{
|
|
37
|
+
entityId: "integrations:integration_credentials",
|
|
38
|
+
tenantId: scope.tenantId,
|
|
39
|
+
organizationId: scope.organizationId,
|
|
40
|
+
deletedAt: null
|
|
41
|
+
},
|
|
42
|
+
void 0,
|
|
43
|
+
scope
|
|
44
|
+
);
|
|
45
|
+
if (!existing) {
|
|
46
|
+
const created = em.create(EncryptionMap, {
|
|
47
|
+
entityId: "integrations:integration_credentials",
|
|
48
|
+
tenantId: scope.tenantId,
|
|
49
|
+
organizationId: scope.organizationId,
|
|
50
|
+
fieldsJson: credentialsEncryptionSpec,
|
|
51
|
+
isActive: true,
|
|
52
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
53
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
54
|
+
});
|
|
55
|
+
em.persist(created);
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
existing.fieldsJson = credentialsEncryptionSpec;
|
|
59
|
+
existing.isActive = true;
|
|
60
|
+
}
|
|
61
|
+
async function resolveCredentialsDek(scope) {
|
|
62
|
+
const kms = createKmsService();
|
|
63
|
+
const existing = await kms.getTenantDek(scope.tenantId);
|
|
64
|
+
if (existing?.key) return existing.key;
|
|
65
|
+
const created = await kms.createTenantDek(scope.tenantId);
|
|
66
|
+
if (created?.key) return created.key;
|
|
67
|
+
return deriveDekFromSecret(resolveFallbackEncryptionSecret(), scope.tenantId);
|
|
68
|
+
}
|
|
69
|
+
async function encryptCredentialsBlob(credentials, scope) {
|
|
70
|
+
const dek = await resolveCredentialsDek(scope);
|
|
71
|
+
const payload = encryptWithAesGcm(JSON.stringify(credentials), dek);
|
|
72
|
+
return { [ENCRYPTED_CREDENTIALS_BLOB_KEY]: payload.value };
|
|
73
|
+
}
|
|
74
|
+
async function decryptCredentialsBlob(credentials, scope) {
|
|
75
|
+
const encrypted = credentials[ENCRYPTED_CREDENTIALS_BLOB_KEY];
|
|
76
|
+
if (typeof encrypted !== "string" || !encrypted) return credentials;
|
|
77
|
+
const dek = await resolveCredentialsDek(scope);
|
|
78
|
+
const decryptedRaw = decryptWithAesGcm(encrypted, dek);
|
|
79
|
+
if (!decryptedRaw) return {};
|
|
80
|
+
try {
|
|
81
|
+
const parsed = JSON.parse(decryptedRaw);
|
|
82
|
+
return parsed && typeof parsed === "object" && !Array.isArray(parsed) ? parsed : {};
|
|
83
|
+
} catch {
|
|
84
|
+
return {};
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
async getRaw(integrationId, scope) {
|
|
89
|
+
const row = await findOneWithDecryption(
|
|
90
|
+
em,
|
|
91
|
+
IntegrationCredentials,
|
|
92
|
+
{
|
|
93
|
+
integrationId,
|
|
94
|
+
organizationId: scope.organizationId,
|
|
95
|
+
tenantId: scope.tenantId,
|
|
96
|
+
deletedAt: null
|
|
97
|
+
},
|
|
98
|
+
void 0,
|
|
99
|
+
scope
|
|
100
|
+
);
|
|
101
|
+
if (!row) return null;
|
|
102
|
+
return decryptCredentialsBlob(row.credentials, scope);
|
|
103
|
+
},
|
|
104
|
+
async resolve(integrationId, scope) {
|
|
105
|
+
const direct = await this.getRaw(integrationId, scope);
|
|
106
|
+
if (direct) return direct;
|
|
107
|
+
const definition = getIntegration(integrationId);
|
|
108
|
+
if (!definition?.bundleId) return null;
|
|
109
|
+
return this.getRaw(definition.bundleId, scope);
|
|
110
|
+
},
|
|
111
|
+
async save(integrationId, credentials, scope) {
|
|
112
|
+
await ensureCredentialsEncryptionMap(scope);
|
|
113
|
+
const encryptedCredentials = await encryptCredentialsBlob(credentials, scope);
|
|
114
|
+
const row = await findOneWithDecryption(
|
|
115
|
+
em,
|
|
116
|
+
IntegrationCredentials,
|
|
117
|
+
{
|
|
118
|
+
integrationId,
|
|
119
|
+
organizationId: scope.organizationId,
|
|
120
|
+
tenantId: scope.tenantId,
|
|
121
|
+
deletedAt: null
|
|
122
|
+
},
|
|
123
|
+
void 0,
|
|
124
|
+
scope
|
|
125
|
+
);
|
|
126
|
+
if (row) {
|
|
127
|
+
row.credentials = encryptedCredentials;
|
|
128
|
+
await em.flush();
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
const created = em.create(IntegrationCredentials, {
|
|
132
|
+
integrationId,
|
|
133
|
+
credentials: encryptedCredentials,
|
|
134
|
+
organizationId: scope.organizationId,
|
|
135
|
+
tenantId: scope.tenantId
|
|
136
|
+
});
|
|
137
|
+
await em.persistAndFlush(created);
|
|
138
|
+
},
|
|
139
|
+
async saveField(integrationId, fieldKey, value, scope) {
|
|
140
|
+
const current = await this.getRaw(integrationId, scope) ?? {};
|
|
141
|
+
const updated = { ...current, [fieldKey]: value };
|
|
142
|
+
await this.save(integrationId, updated, scope);
|
|
143
|
+
return updated;
|
|
144
|
+
},
|
|
145
|
+
getSchema(integrationId) {
|
|
146
|
+
const definition = getIntegration(integrationId);
|
|
147
|
+
if (!definition) return void 0;
|
|
148
|
+
if (definition.bundleId) {
|
|
149
|
+
const bundle = getBundle(definition.bundleId);
|
|
150
|
+
return bundle?.credentials ?? resolveIntegrationCredentialsSchema(integrationId);
|
|
151
|
+
}
|
|
152
|
+
return definition.credentials ?? resolveIntegrationCredentialsSchema(integrationId);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
export {
|
|
157
|
+
createCredentialsService
|
|
158
|
+
};
|
|
159
|
+
//# sourceMappingURL=credentials-service.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/integrations/lib/credentials-service.ts"],
|
|
4
|
+
"sourcesContent": ["import crypto from 'node:crypto'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { decryptWithAesGcm, encryptWithAesGcm } from '@open-mercato/shared/lib/encryption/aes'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { createKmsService } from '@open-mercato/shared/lib/encryption/kms'\nimport { getBundle, getIntegration, resolveIntegrationCredentialsSchema } from '@open-mercato/shared/modules/integrations/types'\nimport { EncryptionMap } from '../../entities/data/entities'\nimport { IntegrationCredentials } from '../data/entities'\nimport type { IntegrationScope } from './types'\n\nconst ENCRYPTED_CREDENTIALS_BLOB_KEY = '__om_encrypted_credentials_blob_v1'\nconst DERIVED_KEY_CONTEXT = 'integrations.credentials'\n\nfunction resolveFallbackEncryptionSecret(): string {\n const candidates = [\n process.env.TENANT_DATA_ENCRYPTION_FALLBACK_KEY,\n process.env.TENANT_DATA_ENCRYPTION_KEY,\n process.env.AUTH_SECRET,\n process.env.NEXTAUTH_SECRET,\n ]\n\n for (const value of candidates) {\n const normalized = value?.trim()\n if (normalized) return normalized\n }\n\n if (process.env.NODE_ENV !== 'production') return 'om-dev-tenant-encryption'\n\n console.warn(\n '[integrations.credentials] No encryption secret configured; using emergency fallback secret. Configure TENANT_DATA_ENCRYPTION_FALLBACK_KEY immediately.',\n )\n return 'om-emergency-fallback-rotate-me'\n}\n\nfunction deriveDekFromSecret(secret: string, tenantId: string): string {\n return crypto\n .createHash('sha256')\n .update(`${DERIVED_KEY_CONTEXT}:${tenantId}:${secret}`)\n .digest()\n .toString('base64')\n}\n\nexport function createCredentialsService(em: EntityManager) {\n const credentialsEncryptionSpec = [{ field: 'credentials' }]\n\n async function ensureCredentialsEncryptionMap(scope: IntegrationScope): Promise<void> {\n const existing = await findOneWithDecryption(\n em,\n EncryptionMap,\n {\n entityId: 'integrations:integration_credentials',\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n\n if (!existing) {\n const created = em.create(EncryptionMap, {\n entityId: 'integrations:integration_credentials',\n tenantId: scope.tenantId,\n organizationId: scope.organizationId,\n fieldsJson: credentialsEncryptionSpec,\n isActive: true,\n createdAt: new Date(),\n updatedAt: new Date(),\n })\n em.persist(created)\n return\n }\n\n existing.fieldsJson = credentialsEncryptionSpec\n existing.isActive = true\n }\n\n async function resolveCredentialsDek(scope: IntegrationScope): Promise<string> {\n const kms = createKmsService()\n const existing = await kms.getTenantDek(scope.tenantId)\n if (existing?.key) return existing.key\n\n const created = await kms.createTenantDek(scope.tenantId)\n if (created?.key) return created.key\n\n return deriveDekFromSecret(resolveFallbackEncryptionSecret(), scope.tenantId)\n }\n\n async function encryptCredentialsBlob(\n credentials: Record<string, unknown>,\n scope: IntegrationScope,\n ): Promise<Record<string, unknown>> {\n const dek = await resolveCredentialsDek(scope)\n const payload = encryptWithAesGcm(JSON.stringify(credentials), dek)\n return { [ENCRYPTED_CREDENTIALS_BLOB_KEY]: payload.value }\n }\n\n async function decryptCredentialsBlob(\n credentials: Record<string, unknown>,\n scope: IntegrationScope,\n ): Promise<Record<string, unknown>> {\n const encrypted = credentials[ENCRYPTED_CREDENTIALS_BLOB_KEY]\n if (typeof encrypted !== 'string' || !encrypted) return credentials\n\n const dek = await resolveCredentialsDek(scope)\n const decryptedRaw = decryptWithAesGcm(encrypted, dek)\n if (!decryptedRaw) return {}\n\n try {\n const parsed = JSON.parse(decryptedRaw) as unknown\n return parsed && typeof parsed === 'object' && !Array.isArray(parsed)\n ? (parsed as Record<string, unknown>)\n : {}\n } catch {\n return {}\n }\n }\n\n return {\n async getRaw(integrationId: string, scope: IntegrationScope): Promise<Record<string, unknown> | null> {\n const row = await findOneWithDecryption(\n em,\n IntegrationCredentials,\n {\n integrationId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n if (!row) return null\n return decryptCredentialsBlob(row.credentials, scope)\n },\n\n async resolve(integrationId: string, scope: IntegrationScope): Promise<Record<string, unknown> | null> {\n const direct = await this.getRaw(integrationId, scope)\n if (direct) return direct\n\n const definition = getIntegration(integrationId)\n if (!definition?.bundleId) return null\n return this.getRaw(definition.bundleId, scope)\n },\n\n async save(integrationId: string, credentials: Record<string, unknown>, scope: IntegrationScope): Promise<void> {\n await ensureCredentialsEncryptionMap(scope)\n const encryptedCredentials = await encryptCredentialsBlob(credentials, scope)\n\n const row = await findOneWithDecryption(\n em,\n IntegrationCredentials,\n {\n integrationId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n\n if (row) {\n row.credentials = encryptedCredentials\n await em.flush()\n return\n }\n\n const created = em.create(IntegrationCredentials, {\n integrationId,\n credentials: encryptedCredentials,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n })\n await em.persistAndFlush(created)\n },\n\n async saveField(\n integrationId: string,\n fieldKey: string,\n value: unknown,\n scope: IntegrationScope,\n ): Promise<Record<string, unknown>> {\n const current = (await this.getRaw(integrationId, scope)) ?? {}\n const updated = { ...current, [fieldKey]: value }\n await this.save(integrationId, updated, scope)\n return updated\n },\n\n getSchema(integrationId: string) {\n const definition = getIntegration(integrationId)\n if (!definition) return undefined\n\n if (definition.bundleId) {\n const bundle = getBundle(definition.bundleId)\n return bundle?.credentials ?? resolveIntegrationCredentialsSchema(integrationId)\n }\n\n return definition.credentials ?? resolveIntegrationCredentialsSchema(integrationId)\n },\n }\n}\n\nexport type CredentialsService = ReturnType<typeof createCredentialsService>\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { getIntegration, getBundle } from "@open-mercato/shared/modules/integrations/types";
|
|
2
|
+
function createHealthService(container, stateService, logService) {
|
|
3
|
+
return {
|
|
4
|
+
async runHealthCheck(integrationId, scope) {
|
|
5
|
+
const definition = getIntegration(integrationId);
|
|
6
|
+
const healthConfig = definition?.healthCheck ?? (definition?.bundleId ? getBundle(definition.bundleId)?.healthCheck : void 0);
|
|
7
|
+
if (!healthConfig?.service) {
|
|
8
|
+
return { status: "unhealthy", message: "No health check configured" };
|
|
9
|
+
}
|
|
10
|
+
let result;
|
|
11
|
+
try {
|
|
12
|
+
const checker = container.resolve(healthConfig.service);
|
|
13
|
+
const credentialsService = container.resolve("integrationCredentialsService");
|
|
14
|
+
const credentials = await credentialsService.resolve(integrationId, scope);
|
|
15
|
+
result = await checker.check(credentials, scope);
|
|
16
|
+
} catch (error) {
|
|
17
|
+
const message = error instanceof Error ? error.message : "Health check failed";
|
|
18
|
+
result = { status: "unhealthy", message };
|
|
19
|
+
}
|
|
20
|
+
await stateService.upsert(integrationId, {
|
|
21
|
+
lastHealthStatus: result.status,
|
|
22
|
+
lastHealthCheckedAt: /* @__PURE__ */ new Date()
|
|
23
|
+
}, scope);
|
|
24
|
+
const logger = logService.scoped(integrationId, scope);
|
|
25
|
+
if (result.status === "healthy") {
|
|
26
|
+
await logger.info(`Health check passed`, { status: result.status, ...result.details });
|
|
27
|
+
} else {
|
|
28
|
+
await logger.warn(`Health check: ${result.status}`, { status: result.status, message: result.message, ...result.details });
|
|
29
|
+
}
|
|
30
|
+
return result;
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
export {
|
|
35
|
+
createHealthService
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=health-service.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/integrations/lib/health-service.ts"],
|
|
4
|
+
"sourcesContent": ["import type { AwilixContainer } from 'awilix'\nimport type { IntegrationStateService } from './state-service'\nimport type { IntegrationLogService } from './log-service'\nimport { getIntegration, getBundle } from '@open-mercato/shared/modules/integrations/types'\nimport type { IntegrationScope } from './types'\n\ntype HealthCheckResult = {\n status: 'healthy' | 'degraded' | 'unhealthy'\n message?: string\n details?: Record<string, unknown>\n}\n\ntype HealthCheckService = {\n check: (credentials: Record<string, unknown> | null, scope: IntegrationScope) => Promise<HealthCheckResult>\n}\n\nexport function createHealthService(\n container: AwilixContainer,\n stateService: IntegrationStateService,\n logService: IntegrationLogService,\n) {\n return {\n async runHealthCheck(integrationId: string, scope: IntegrationScope): Promise<HealthCheckResult> {\n const definition = getIntegration(integrationId)\n const healthConfig = definition?.healthCheck ?? (definition?.bundleId ? getBundle(definition.bundleId)?.healthCheck : undefined)\n\n if (!healthConfig?.service) {\n return { status: 'unhealthy', message: 'No health check configured' }\n }\n\n let result: HealthCheckResult\n try {\n const checker = container.resolve<HealthCheckService>(healthConfig.service)\n const credentialsService = container.resolve<{ resolve: (id: string, scope: IntegrationScope) => Promise<Record<string, unknown> | null> }>('integrationCredentialsService')\n const credentials = await credentialsService.resolve(integrationId, scope)\n result = await checker.check(credentials, scope)\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Health check failed'\n result = { status: 'unhealthy', message }\n }\n\n await stateService.upsert(integrationId, {\n lastHealthStatus: result.status,\n lastHealthCheckedAt: new Date(),\n }, scope)\n\n const logger = logService.scoped(integrationId, scope)\n if (result.status === 'healthy') {\n await logger.info(`Health check passed`, { status: result.status, ...result.details })\n } else {\n await logger.warn(`Health check: ${result.status}`, { status: result.status, message: result.message, ...result.details })\n }\n\n return result\n },\n }\n}\n\nexport type IntegrationHealthService = ReturnType<typeof createHealthService>\n"],
|
|
5
|
+
"mappings": "AAGA,SAAS,gBAAgB,iBAAiB;AAanC,SAAS,oBACd,WACA,cACA,YACA;AACA,SAAO;AAAA,IACL,MAAM,eAAe,eAAuB,OAAqD;AAC/F,YAAM,aAAa,eAAe,aAAa;AAC/C,YAAM,eAAe,YAAY,gBAAgB,YAAY,WAAW,UAAU,WAAW,QAAQ,GAAG,cAAc;AAEtH,UAAI,CAAC,cAAc,SAAS;AAC1B,eAAO,EAAE,QAAQ,aAAa,SAAS,6BAA6B;AAAA,MACtE;AAEA,UAAI;AACJ,UAAI;AACF,cAAM,UAAU,UAAU,QAA4B,aAAa,OAAO;AAC1E,cAAM,qBAAqB,UAAU,QAAuG,+BAA+B;AAC3K,cAAM,cAAc,MAAM,mBAAmB,QAAQ,eAAe,KAAK;AACzE,iBAAS,MAAM,QAAQ,MAAM,aAAa,KAAK;AAAA,MACjD,SAAS,OAAO;AACd,cAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU;AACzD,iBAAS,EAAE,QAAQ,aAAa,QAAQ;AAAA,MAC1C;AAEA,YAAM,aAAa,OAAO,eAAe;AAAA,QACvC,kBAAkB,OAAO;AAAA,QACzB,qBAAqB,oBAAI,KAAK;AAAA,MAChC,GAAG,KAAK;AAER,YAAM,SAAS,WAAW,OAAO,eAAe,KAAK;AACrD,UAAI,OAAO,WAAW,WAAW;AAC/B,cAAM,OAAO,KAAK,uBAAuB,EAAE,QAAQ,OAAO,QAAQ,GAAG,OAAO,QAAQ,CAAC;AAAA,MACvF,OAAO;AACL,cAAM,OAAO,KAAK,iBAAiB,OAAO,MAAM,IAAI,EAAE,QAAQ,OAAO,QAAQ,SAAS,OAAO,SAAS,GAAG,OAAO,QAAQ,CAAC;AAAA,MAC3H;AAEA,aAAO;AAAA,IACT;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { findWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
2
|
+
import { IntegrationLog } from "../data/entities.js";
|
|
3
|
+
function createIntegrationLogService(em) {
|
|
4
|
+
return {
|
|
5
|
+
async write(input, scope) {
|
|
6
|
+
const row = em.create(IntegrationLog, {
|
|
7
|
+
integrationId: input.integrationId,
|
|
8
|
+
runId: input.runId,
|
|
9
|
+
scopeEntityType: input.scopeEntityType,
|
|
10
|
+
scopeEntityId: input.scopeEntityId,
|
|
11
|
+
level: input.level,
|
|
12
|
+
message: input.message,
|
|
13
|
+
code: input.code,
|
|
14
|
+
payload: input.payload,
|
|
15
|
+
organizationId: scope.organizationId,
|
|
16
|
+
tenantId: scope.tenantId
|
|
17
|
+
});
|
|
18
|
+
await em.persistAndFlush(row);
|
|
19
|
+
return row;
|
|
20
|
+
},
|
|
21
|
+
scoped(integrationId, scope) {
|
|
22
|
+
return {
|
|
23
|
+
info: (message, payload) => this.write({ integrationId, level: "info", message, payload }, scope),
|
|
24
|
+
warn: (message, payload) => this.write({ integrationId, level: "warn", message, payload }, scope),
|
|
25
|
+
error: (message, payload) => this.write({ integrationId, level: "error", message, payload }, scope)
|
|
26
|
+
};
|
|
27
|
+
},
|
|
28
|
+
async query(query, scope) {
|
|
29
|
+
const where = {
|
|
30
|
+
organizationId: scope.organizationId,
|
|
31
|
+
tenantId: scope.tenantId
|
|
32
|
+
};
|
|
33
|
+
if (query.integrationId) where.integrationId = query.integrationId;
|
|
34
|
+
if (query.level) where.level = query.level;
|
|
35
|
+
if (query.runId) where.runId = query.runId;
|
|
36
|
+
if (query.entityType) where.scopeEntityType = query.entityType;
|
|
37
|
+
if (query.entityId) where.scopeEntityId = query.entityId;
|
|
38
|
+
const items = await findWithDecryption(
|
|
39
|
+
em,
|
|
40
|
+
IntegrationLog,
|
|
41
|
+
where,
|
|
42
|
+
{
|
|
43
|
+
orderBy: { createdAt: "DESC" },
|
|
44
|
+
limit: query.pageSize,
|
|
45
|
+
offset: (query.page - 1) * query.pageSize
|
|
46
|
+
},
|
|
47
|
+
scope
|
|
48
|
+
);
|
|
49
|
+
const total = await em.count(IntegrationLog, where);
|
|
50
|
+
return { items, total };
|
|
51
|
+
},
|
|
52
|
+
async pruneOlderThan(days, scope) {
|
|
53
|
+
const threshold = new Date(Date.now() - days * 24 * 60 * 60 * 1e3);
|
|
54
|
+
const deletedCount = await em.nativeDelete(IntegrationLog, {
|
|
55
|
+
organizationId: scope.organizationId,
|
|
56
|
+
tenantId: scope.tenantId,
|
|
57
|
+
createdAt: { $lt: threshold }
|
|
58
|
+
});
|
|
59
|
+
return deletedCount;
|
|
60
|
+
}
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
export {
|
|
64
|
+
createIntegrationLogService
|
|
65
|
+
};
|
|
66
|
+
//# sourceMappingURL=log-service.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/integrations/lib/log-service.ts"],
|
|
4
|
+
"sourcesContent": ["import type { EntityManager, FilterQuery } from '@mikro-orm/postgresql'\nimport { findWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport type { ListIntegrationLogsQuery } from '../data/validators'\nimport { IntegrationLog } from '../data/entities'\nimport type { IntegrationScope } from './types'\n\ntype LogInput = {\n integrationId: string\n runId?: string | null\n scopeEntityType?: string | null\n scopeEntityId?: string | null\n level: 'info' | 'warn' | 'error'\n message: string\n code?: string | null\n payload?: Record<string, unknown> | null\n}\n\nexport function createIntegrationLogService(em: EntityManager) {\n return {\n async write(input: LogInput, scope: IntegrationScope): Promise<IntegrationLog> {\n const row = em.create(IntegrationLog, {\n integrationId: input.integrationId,\n runId: input.runId,\n scopeEntityType: input.scopeEntityType,\n scopeEntityId: input.scopeEntityId,\n level: input.level,\n message: input.message,\n code: input.code,\n payload: input.payload,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n })\n await em.persistAndFlush(row)\n return row\n },\n\n scoped(integrationId: string, scope: IntegrationScope) {\n return {\n info: (message: string, payload?: Record<string, unknown>) => this.write({ integrationId, level: 'info', message, payload }, scope),\n warn: (message: string, payload?: Record<string, unknown>) => this.write({ integrationId, level: 'warn', message, payload }, scope),\n error: (message: string, payload?: Record<string, unknown>) => this.write({ integrationId, level: 'error', message, payload }, scope),\n }\n },\n\n async query(query: ListIntegrationLogsQuery, scope: IntegrationScope): Promise<{ items: IntegrationLog[]; total: number }> {\n const where: FilterQuery<IntegrationLog> = {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n }\n\n if (query.integrationId) where.integrationId = query.integrationId\n if (query.level) where.level = query.level\n if (query.runId) where.runId = query.runId\n if (query.entityType) where.scopeEntityType = query.entityType\n if (query.entityId) where.scopeEntityId = query.entityId\n\n const items = await findWithDecryption(\n em,\n IntegrationLog,\n where,\n {\n orderBy: { createdAt: 'DESC' },\n limit: query.pageSize,\n offset: (query.page - 1) * query.pageSize,\n },\n scope,\n )\n const total = await em.count(IntegrationLog, where)\n return { items, total }\n },\n\n async pruneOlderThan(days: number, scope: IntegrationScope): Promise<number> {\n const threshold = new Date(Date.now() - days * 24 * 60 * 60 * 1000)\n const deletedCount = await em.nativeDelete(IntegrationLog, {\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n createdAt: { $lt: threshold },\n })\n return deletedCount\n },\n }\n}\n\nexport type IntegrationLogService = ReturnType<typeof createIntegrationLogService>\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,0BAA0B;AAEnC,SAAS,sBAAsB;AAcxB,SAAS,4BAA4B,IAAmB;AAC7D,SAAO;AAAA,IACL,MAAM,MAAM,OAAiB,OAAkD;AAC7E,YAAM,MAAM,GAAG,OAAO,gBAAgB;AAAA,QACpC,eAAe,MAAM;AAAA,QACrB,OAAO,MAAM;AAAA,QACb,iBAAiB,MAAM;AAAA,QACvB,eAAe,MAAM;AAAA,QACrB,OAAO,MAAM;AAAA,QACb,SAAS,MAAM;AAAA,QACf,MAAM,MAAM;AAAA,QACZ,SAAS,MAAM;AAAA,QACf,gBAAgB,MAAM;AAAA,QACtB,UAAU,MAAM;AAAA,MAClB,CAAC;AACD,YAAM,GAAG,gBAAgB,GAAG;AAC5B,aAAO;AAAA,IACT;AAAA,IAEA,OAAO,eAAuB,OAAyB;AACrD,aAAO;AAAA,QACL,MAAM,CAAC,SAAiB,YAAsC,KAAK,MAAM,EAAE,eAAe,OAAO,QAAQ,SAAS,QAAQ,GAAG,KAAK;AAAA,QAClI,MAAM,CAAC,SAAiB,YAAsC,KAAK,MAAM,EAAE,eAAe,OAAO,QAAQ,SAAS,QAAQ,GAAG,KAAK;AAAA,QAClI,OAAO,CAAC,SAAiB,YAAsC,KAAK,MAAM,EAAE,eAAe,OAAO,SAAS,SAAS,QAAQ,GAAG,KAAK;AAAA,MACtI;AAAA,IACF;AAAA,IAEA,MAAM,MAAM,OAAiC,OAA8E;AACzH,YAAM,QAAqC;AAAA,QACzC,gBAAgB,MAAM;AAAA,QACtB,UAAU,MAAM;AAAA,MAClB;AAEA,UAAI,MAAM,cAAe,OAAM,gBAAgB,MAAM;AACrD,UAAI,MAAM,MAAO,OAAM,QAAQ,MAAM;AACrC,UAAI,MAAM,MAAO,OAAM,QAAQ,MAAM;AACrC,UAAI,MAAM,WAAY,OAAM,kBAAkB,MAAM;AACpD,UAAI,MAAM,SAAU,OAAM,gBAAgB,MAAM;AAEhD,YAAM,QAAQ,MAAM;AAAA,QAClB;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,UACE,SAAS,EAAE,WAAW,OAAO;AAAA,UAC7B,OAAO,MAAM;AAAA,UACb,SAAS,MAAM,OAAO,KAAK,MAAM;AAAA,QACnC;AAAA,QACA;AAAA,MACF;AACA,YAAM,QAAQ,MAAM,GAAG,MAAM,gBAAgB,KAAK;AAClD,aAAO,EAAE,OAAO,MAAM;AAAA,IACxB;AAAA,IAEA,MAAM,eAAe,MAAc,OAA0C;AAC3E,YAAM,YAAY,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,KAAK,GAAI;AAClE,YAAM,eAAe,MAAM,GAAG,aAAa,gBAAgB;AAAA,QACzD,gBAAgB,MAAM;AAAA,QACtB,UAAU,MAAM;AAAA,QAChB,WAAW,EAAE,KAAK,UAAU;AAAA,MAC9B,CAAC;AACD,aAAO;AAAA,IACT;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getAllBundles,
|
|
3
|
+
getAllIntegrations,
|
|
4
|
+
getBundle,
|
|
5
|
+
getIntegration
|
|
6
|
+
} from "@open-mercato/shared/modules/integrations/types";
|
|
7
|
+
function listIntegrationRegistry() {
|
|
8
|
+
return {
|
|
9
|
+
integrations: getAllIntegrations(),
|
|
10
|
+
bundles: getAllBundles()
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
function getIntegrationDetail(integrationId) {
|
|
14
|
+
const integration = getIntegration(integrationId);
|
|
15
|
+
if (!integration) return null;
|
|
16
|
+
const bundle = integration.bundleId ? getBundle(integration.bundleId) : void 0;
|
|
17
|
+
return {
|
|
18
|
+
integration,
|
|
19
|
+
bundle
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function resolveDefaultApiVersion(versions) {
|
|
23
|
+
if (!versions?.length) return void 0;
|
|
24
|
+
const explicitDefault = versions.find((version) => version.default);
|
|
25
|
+
if (explicitDefault) return explicitDefault.id;
|
|
26
|
+
return versions[0]?.id;
|
|
27
|
+
}
|
|
28
|
+
export {
|
|
29
|
+
getIntegrationDetail,
|
|
30
|
+
listIntegrationRegistry,
|
|
31
|
+
resolveDefaultApiVersion
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=registry-service.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/integrations/lib/registry-service.ts"],
|
|
4
|
+
"sourcesContent": ["import {\n getAllBundles,\n getAllIntegrations,\n getBundle,\n getIntegration,\n type ApiVersionDefinition,\n type IntegrationBundle,\n type IntegrationDefinition,\n} from '@open-mercato/shared/modules/integrations/types'\n\nexport type IntegrationDetail = {\n integration: IntegrationDefinition\n bundle?: IntegrationBundle\n selectedApiVersion?: string\n}\n\nexport function listIntegrationRegistry(): {\n integrations: IntegrationDefinition[]\n bundles: IntegrationBundle[]\n} {\n return {\n integrations: getAllIntegrations(),\n bundles: getAllBundles(),\n }\n}\n\nexport function getIntegrationDetail(integrationId: string): IntegrationDetail | null {\n const integration = getIntegration(integrationId)\n if (!integration) return null\n const bundle = integration.bundleId ? getBundle(integration.bundleId) : undefined\n return {\n integration,\n bundle,\n }\n}\n\nexport function resolveDefaultApiVersion(versions: ApiVersionDefinition[] | undefined): string | undefined {\n if (!versions?.length) return undefined\n const explicitDefault = versions.find((version) => version.default)\n if (explicitDefault) return explicitDefault.id\n return versions[0]?.id\n}\n"],
|
|
5
|
+
"mappings": "AAAA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OAIK;AAQA,SAAS,0BAGd;AACA,SAAO;AAAA,IACL,cAAc,mBAAmB;AAAA,IACjC,SAAS,cAAc;AAAA,EACzB;AACF;AAEO,SAAS,qBAAqB,eAAiD;AACpF,QAAM,cAAc,eAAe,aAAa;AAChD,MAAI,CAAC,YAAa,QAAO;AACzB,QAAM,SAAS,YAAY,WAAW,UAAU,YAAY,QAAQ,IAAI;AACxE,SAAO;AAAA,IACL;AAAA,IACA;AAAA,EACF;AACF;AAEO,SAAS,yBAAyB,UAAkE;AACzG,MAAI,CAAC,UAAU,OAAQ,QAAO;AAC9B,QAAM,kBAAkB,SAAS,KAAK,CAAC,YAAY,QAAQ,OAAO;AAClE,MAAI,gBAAiB,QAAO,gBAAgB;AAC5C,SAAO,SAAS,CAAC,GAAG;AACtB;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { findOneWithDecryption } from "@open-mercato/shared/lib/encryption/find";
|
|
2
|
+
import { IntegrationState } from "../data/entities.js";
|
|
3
|
+
function createIntegrationStateService(em) {
|
|
4
|
+
return {
|
|
5
|
+
async get(integrationId, scope) {
|
|
6
|
+
return findOneWithDecryption(
|
|
7
|
+
em,
|
|
8
|
+
IntegrationState,
|
|
9
|
+
{
|
|
10
|
+
integrationId,
|
|
11
|
+
organizationId: scope.organizationId,
|
|
12
|
+
tenantId: scope.tenantId,
|
|
13
|
+
deletedAt: null
|
|
14
|
+
},
|
|
15
|
+
void 0,
|
|
16
|
+
scope
|
|
17
|
+
);
|
|
18
|
+
},
|
|
19
|
+
async upsert(integrationId, input, scope) {
|
|
20
|
+
const current = await this.get(integrationId, scope);
|
|
21
|
+
if (current) {
|
|
22
|
+
if (input.isEnabled !== void 0) current.isEnabled = input.isEnabled;
|
|
23
|
+
if (input.apiVersion !== void 0) current.apiVersion = input.apiVersion;
|
|
24
|
+
if (input.reauthRequired !== void 0) current.reauthRequired = input.reauthRequired;
|
|
25
|
+
if (input.lastHealthStatus !== void 0) current.lastHealthStatus = input.lastHealthStatus;
|
|
26
|
+
if (input.lastHealthCheckedAt !== void 0) current.lastHealthCheckedAt = input.lastHealthCheckedAt;
|
|
27
|
+
await em.flush();
|
|
28
|
+
return current;
|
|
29
|
+
}
|
|
30
|
+
const created = em.create(IntegrationState, {
|
|
31
|
+
integrationId,
|
|
32
|
+
isEnabled: input.isEnabled ?? true,
|
|
33
|
+
apiVersion: input.apiVersion,
|
|
34
|
+
reauthRequired: input.reauthRequired ?? false,
|
|
35
|
+
lastHealthStatus: input.lastHealthStatus,
|
|
36
|
+
lastHealthCheckedAt: input.lastHealthCheckedAt,
|
|
37
|
+
organizationId: scope.organizationId,
|
|
38
|
+
tenantId: scope.tenantId
|
|
39
|
+
});
|
|
40
|
+
await em.persistAndFlush(created);
|
|
41
|
+
return created;
|
|
42
|
+
},
|
|
43
|
+
async resolveApiVersion(integrationId, scope) {
|
|
44
|
+
const state = await this.get(integrationId, scope);
|
|
45
|
+
return state?.apiVersion ?? void 0;
|
|
46
|
+
},
|
|
47
|
+
async setReauthRequired(integrationId, required, scope) {
|
|
48
|
+
return this.upsert(integrationId, { reauthRequired: required }, scope);
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
export {
|
|
53
|
+
createIntegrationStateService
|
|
54
|
+
};
|
|
55
|
+
//# sourceMappingURL=state-service.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../src/modules/integrations/lib/state-service.ts"],
|
|
4
|
+
"sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport { findOneWithDecryption } from '@open-mercato/shared/lib/encryption/find'\nimport { IntegrationState } from '../data/entities'\nimport type { IntegrationScope } from './types'\n\nexport function createIntegrationStateService(em: EntityManager) {\n return {\n async get(integrationId: string, scope: IntegrationScope): Promise<IntegrationState | null> {\n return findOneWithDecryption(\n em,\n IntegrationState,\n {\n integrationId,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n deletedAt: null,\n },\n undefined,\n scope,\n )\n },\n\n async upsert(\n integrationId: string,\n input: Partial<Pick<IntegrationState, 'isEnabled' | 'apiVersion' | 'reauthRequired' | 'lastHealthStatus' | 'lastHealthCheckedAt'>>,\n scope: IntegrationScope,\n ): Promise<IntegrationState> {\n const current = await this.get(integrationId, scope)\n if (current) {\n if (input.isEnabled !== undefined) current.isEnabled = input.isEnabled\n if (input.apiVersion !== undefined) current.apiVersion = input.apiVersion\n if (input.reauthRequired !== undefined) current.reauthRequired = input.reauthRequired\n if (input.lastHealthStatus !== undefined) current.lastHealthStatus = input.lastHealthStatus\n if (input.lastHealthCheckedAt !== undefined) current.lastHealthCheckedAt = input.lastHealthCheckedAt\n await em.flush()\n return current\n }\n\n const created = em.create(IntegrationState, {\n integrationId,\n isEnabled: input.isEnabled ?? true,\n apiVersion: input.apiVersion,\n reauthRequired: input.reauthRequired ?? false,\n lastHealthStatus: input.lastHealthStatus,\n lastHealthCheckedAt: input.lastHealthCheckedAt,\n organizationId: scope.organizationId,\n tenantId: scope.tenantId,\n })\n await em.persistAndFlush(created)\n return created\n },\n\n async resolveApiVersion(integrationId: string, scope: IntegrationScope): Promise<string | undefined> {\n const state = await this.get(integrationId, scope)\n return state?.apiVersion ?? undefined\n },\n\n async setReauthRequired(integrationId: string, required: boolean, scope: IntegrationScope): Promise<IntegrationState> {\n return this.upsert(integrationId, { reauthRequired: required }, scope)\n },\n }\n}\n\nexport type IntegrationStateService = ReturnType<typeof createIntegrationStateService>\n"],
|
|
5
|
+
"mappings": "AACA,SAAS,6BAA6B;AACtC,SAAS,wBAAwB;AAG1B,SAAS,8BAA8B,IAAmB;AAC/D,SAAO;AAAA,IACL,MAAM,IAAI,eAAuB,OAA2D;AAC1F,aAAO;AAAA,QACL;AAAA,QACA;AAAA,QACA;AAAA,UACE;AAAA,UACA,gBAAgB,MAAM;AAAA,UACtB,UAAU,MAAM;AAAA,UAChB,WAAW;AAAA,QACb;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,IACF;AAAA,IAEA,MAAM,OACJ,eACA,OACA,OAC2B;AAC3B,YAAM,UAAU,MAAM,KAAK,IAAI,eAAe,KAAK;AACnD,UAAI,SAAS;AACX,YAAI,MAAM,cAAc,OAAW,SAAQ,YAAY,MAAM;AAC7D,YAAI,MAAM,eAAe,OAAW,SAAQ,aAAa,MAAM;AAC/D,YAAI,MAAM,mBAAmB,OAAW,SAAQ,iBAAiB,MAAM;AACvE,YAAI,MAAM,qBAAqB,OAAW,SAAQ,mBAAmB,MAAM;AAC3E,YAAI,MAAM,wBAAwB,OAAW,SAAQ,sBAAsB,MAAM;AACjF,cAAM,GAAG,MAAM;AACf,eAAO;AAAA,MACT;AAEA,YAAM,UAAU,GAAG,OAAO,kBAAkB;AAAA,QAC1C;AAAA,QACA,WAAW,MAAM,aAAa;AAAA,QAC9B,YAAY,MAAM;AAAA,QAClB,gBAAgB,MAAM,kBAAkB;AAAA,QACxC,kBAAkB,MAAM;AAAA,QACxB,qBAAqB,MAAM;AAAA,QAC3B,gBAAgB,MAAM;AAAA,QACtB,UAAU,MAAM;AAAA,MAClB,CAAC;AACD,YAAM,GAAG,gBAAgB,OAAO;AAChC,aAAO;AAAA,IACT;AAAA,IAEA,MAAM,kBAAkB,eAAuB,OAAsD;AACnG,YAAM,QAAQ,MAAM,KAAK,IAAI,eAAe,KAAK;AACjD,aAAO,OAAO,cAAc;AAAA,IAC9B;AAAA,IAEA,MAAM,kBAAkB,eAAuB,UAAmB,OAAoD;AACpH,aAAO,KAAK,OAAO,eAAe,EAAE,gBAAgB,SAAS,GAAG,KAAK;AAAA,IACvE;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
//# sourceMappingURL=types.js.map
|