@open-mercato/sync-akeneo 0.6.2-develop.3467.1.2a1818709d → 0.6.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/sync_akeneo/lib/adapter.ts"],
4
- "sourcesContent": ["import { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { DataSyncAdapter, DataMapping, ImportBatch, ImportItem, ValidationResult } from '@open-mercato/core/modules/data_sync/lib/adapter'\nimport { buildListResumeCursor, buildProductResumeCursor, parseCursor } from './cursor'\nimport { createAkeneoClient } from './client'\nimport { createAkeneoImporter } from './catalog-importer'\nimport { loadAkeneoMapping } from './mapping'\nimport { buildDefaultReconciliationSettings, normalizeAkeneoMapping, type AkeneoEntityType, type AkeneoDataMapping } from './shared'\n\nfunction assertEntityType(entityType: string): AkeneoEntityType {\n if (entityType === 'categories' || entityType === 'attributes' || entityType === 'products') {\n return entityType\n }\n throw new Error(`Unsupported Akeneo entity type: ${entityType}`)\n}\n\nasync function resolveMapping(entityType: AkeneoEntityType, scope: { organizationId: string; tenantId: string }): Promise<AkeneoDataMapping> {\n const container = await createRequestContainer()\n const em = container.resolve('em')\n return loadAkeneoMapping(em, entityType, scope)\n}\n\nexport const akeneoDataSyncAdapter: DataSyncAdapter = {\n providerKey: 'akeneo',\n direction: 'import',\n supportedEntities: ['categories', 'attributes', 'products'],\n\n async getMapping(input): Promise<DataMapping> {\n const entityType = assertEntityType(input.entityType)\n return resolveMapping(entityType, input.scope)\n },\n\n async validateConnection(input): Promise<ValidationResult> {\n try {\n const entityType = assertEntityType(input.entityType)\n const client = createAkeneoClient(input.credentials)\n if (entityType === 'products') {\n await client.listProducts({ batchSize: 1 })\n } else if (entityType === 'categories') {\n await client.listCategories(null, 1)\n } else {\n await client.listFamilies(null, 1)\n }\n\n const discovery = await client.collectDiscoveryData().catch(() => null)\n return {\n ok: true,\n message: 'Akeneo connection validated successfully',\n details: discovery\n ? {\n locales: discovery.locales.length,\n channels: discovery.channels.length,\n attributes: discovery.attributes.length,\n families: discovery.families.length,\n version: discovery.version,\n }\n : undefined,\n }\n } catch (error) {\n return {\n ok: false,\n message: error instanceof Error ? error.message : 'Akeneo validation failed',\n }\n }\n },\n\n async *streamImport(input): AsyncIterable<ImportBatch> {\n const entityType = assertEntityType(input.entityType)\n const mapping = normalizeAkeneoMapping(entityType, input.mapping as unknown as Record<string, unknown>)\n const client = createAkeneoClient(input.credentials)\n const importer = await createAkeneoImporter(client, input.scope)\n\n if (entityType === 'categories') {\n let batchIndex = 0\n let nextUrl = parseCursor(input.cursor)?.nextUrl ?? null\n const safeFullSync = !input.cursor\n const seenCategoryIds = new Set<string>()\n const reconciliation = buildDefaultReconciliationSettings()\n do {\n const page = await client.listCategories(nextUrl, input.batchSize)\n const items: ImportItem[] = []\n const locale = mapping.settings?.categories?.locale ?? 'en_US'\n for (const category of page.items) {\n seenCategoryIds.add(category.code)\n const result = await importer.upsertCategory(category, locale)\n items.push({\n externalId: category.code,\n data: {\n localId: result.localId,\n code: category.code,\n parent: category.parent ?? null,\n },\n action: result.action,\n })\n }\n nextUrl = page.nextUrl\n yield {\n items,\n cursor: buildListResumeCursor(nextUrl),\n hasMore: Boolean(nextUrl),\n totalEstimate: page.totalEstimate ?? undefined,\n processedCount: page.items.length,\n batchIndex,\n }\n batchIndex += 1\n } while (nextUrl)\n if (safeFullSync) {\n const locale = mapping.settings?.categories?.locale ?? 'en_US'\n await importer.reconcileCategories(seenCategoryIds, locale, reconciliation)\n }\n return\n }\n\n if (entityType === 'attributes') {\n const productMapping = await resolveMapping('products', input.scope)\n let batchIndex = 0\n let nextUrl = parseCursor(input.cursor)?.nextUrl ?? null\n const safeFullSync = !input.cursor\n const seenFamilyIds = new Set<string>()\n const reconciliation = buildDefaultReconciliationSettings()\n const locale = productMapping.settings?.products?.locale\n ?? mapping.settings?.categories?.locale\n ?? 'en_US'\n const customFieldItems = await importer.syncMappedCustomFields(productMapping, locale)\n const currentCustomFieldKeys = new Set(\n customFieldItems\n .map((item) => {\n const key = typeof item.data.key === 'string' ? item.data.key : null\n const target = item.data.target === 'variant' ? 'catalog:catalog_product_variant' : item.data.target === 'product' ? 'catalog:catalog_product' : null\n return key && target ? `${target}:${key}` : null\n })\n .filter((value): value is string => Boolean(value)),\n )\n do {\n const page = await client.listFamilies(nextUrl, input.batchSize)\n const items: ImportItem[] = []\n const includeTextAttributes = mapping.settings?.attributes?.includeTextAttributes ?? true\n const includeNumericAttributes = mapping.settings?.attributes?.includeNumericAttributes ?? true\n const familyFilter = mapping.settings?.attributes?.familyCodeFilter ?? []\n if (batchIndex === 0) {\n customFieldItems.forEach((item) => {\n items.push(item)\n })\n }\n for (const family of page.items) {\n if (familyFilter.length > 0 && !familyFilter.includes(family.code)) continue\n seenFamilyIds.add(family.code)\n const result = await importer.upsertAttributeFamily(\n family,\n locale,\n includeTextAttributes,\n includeNumericAttributes,\n )\n if (!result) continue\n items.push({\n externalId: family.code,\n data: {\n localId: result.localId,\n familyCode: family.code,\n },\n action: result.action,\n })\n }\n nextUrl = page.nextUrl\n yield {\n items,\n cursor: buildListResumeCursor(nextUrl),\n hasMore: Boolean(nextUrl),\n totalEstimate: page.totalEstimate ?? undefined,\n processedCount: page.items.length,\n batchIndex,\n }\n batchIndex += 1\n } while (nextUrl)\n if (safeFullSync) {\n await importer.reconcileMappedCustomFieldFieldsets(productMapping)\n await importer.reconcileAttributes({\n seenFamilyExternalIds: seenFamilyIds,\n currentCustomFieldKeys,\n reconciliation,\n })\n }\n return\n }\n\n let batchIndex = 0\n const currentCursor = parseCursor(input.cursor)\n let nextUrl = currentCursor?.nextUrl ?? null\n let updatedAfter = currentCursor?.updatedAfter ?? null\n let maxUpdatedAt = currentCursor?.maxUpdatedAt ?? updatedAfter\n const safeFullSync = !input.cursor\n const seenProductExternalIds = new Set<string>()\n const seenVariantExternalIds = new Set<string>()\n const reconciliation = mapping.settings?.products?.reconciliation ?? buildDefaultReconciliationSettings()\n\n do {\n const productPageSize = Math.min(Math.max(input.batchSize, 1), 10)\n const page = await client.listProducts({\n nextUrl,\n batchSize: productPageSize,\n updatedAfter,\n })\n\n const items: ImportItem[] = []\n for (const product of page.items) {\n try {\n const imported = await importer.upsertProduct(product, mapping)\n for (const item of imported) {\n if (item.data.localProductId) seenProductExternalIds.add(item.externalId)\n if (item.data.localVariantId) seenVariantExternalIds.add(item.externalId)\n items.push(item)\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Akeneo product import failed'\n items.push({\n externalId: product.parent ? `${product.parent}:${product.uuid}` : product.uuid,\n action: 'failed',\n data: {\n errorMessage: message,\n sourceProductUuid: product.uuid,\n sourceIdentifier: product.identifier ?? null,\n sourceParentCode: product.parent ?? null,\n family: product.family ?? null,\n },\n })\n }\n if (typeof product.updated === 'string' && (!maxUpdatedAt || product.updated > maxUpdatedAt)) {\n maxUpdatedAt = product.updated\n }\n }\n\n nextUrl = page.nextUrl\n const nextCursor = nextUrl\n ? buildProductResumeCursor({\n updatedAfter,\n nextUrl,\n maxUpdatedAt,\n })\n : buildProductResumeCursor({\n updatedAfter: maxUpdatedAt ?? updatedAfter,\n nextUrl: null,\n maxUpdatedAt: null,\n })\n\n yield {\n items,\n cursor: nextCursor,\n hasMore: Boolean(nextUrl),\n totalEstimate: page.totalEstimate ?? undefined,\n processedCount: page.items.length,\n refreshCoverageEntityTypes: [\n 'catalog:catalog_product',\n 'catalog:catalog_product_variant',\n ],\n batchIndex,\n }\n batchIndex += 1\n\n if (!nextUrl && maxUpdatedAt) {\n updatedAfter = maxUpdatedAt\n }\n } while (nextUrl)\n\n if (safeFullSync) {\n yield {\n items: [],\n cursor: buildProductResumeCursor({\n updatedAfter: maxUpdatedAt ?? updatedAfter,\n nextUrl: null,\n maxUpdatedAt: null,\n }),\n hasMore: false,\n totalEstimate: undefined,\n processedCount: 0,\n message: 'Reconciling imported Akeneo products after the final batch',\n batchIndex,\n }\n await importer.reconcileMappedCustomFieldFieldsets(mapping)\n await importer.reconcileProducts(seenProductExternalIds, seenVariantExternalIds, reconciliation)\n }\n },\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport type { DataSyncAdapter, DataMapping, ImportBatch, ImportItem, ValidationResult } from '@open-mercato/core/modules/data_sync/lib/adapter'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { buildListResumeCursor, buildProductResumeCursor, parseCursor } from './cursor'\nimport { createAkeneoClient } from './client'\nimport { createAkeneoImporter } from './catalog-importer'\nimport { loadAkeneoMapping } from './mapping'\nimport { buildDefaultReconciliationSettings, normalizeAkeneoMapping, type AkeneoEntityType, type AkeneoDataMapping } from './shared'\n\nfunction assertEntityType(entityType: string): AkeneoEntityType {\n if (entityType === 'categories' || entityType === 'attributes' || entityType === 'products') {\n return entityType\n }\n throw new Error(`Unsupported Akeneo entity type: ${entityType}`)\n}\n\nasync function resolveMapping(entityType: AkeneoEntityType, scope: { organizationId: string; tenantId: string }): Promise<AkeneoDataMapping> {\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n return loadAkeneoMapping(em, entityType, scope)\n}\n\nexport const akeneoDataSyncAdapter: DataSyncAdapter = {\n providerKey: 'akeneo',\n direction: 'import',\n supportedEntities: ['categories', 'attributes', 'products'],\n\n async getMapping(input): Promise<DataMapping> {\n const entityType = assertEntityType(input.entityType)\n return resolveMapping(entityType, input.scope)\n },\n\n async validateConnection(input): Promise<ValidationResult> {\n try {\n const entityType = assertEntityType(input.entityType)\n const client = createAkeneoClient(input.credentials)\n if (entityType === 'products') {\n await client.listProducts({ batchSize: 1 })\n } else if (entityType === 'categories') {\n await client.listCategories(null, 1)\n } else {\n await client.listFamilies(null, 1)\n }\n\n const discovery = await client.collectDiscoveryData().catch(() => null)\n return {\n ok: true,\n message: 'Akeneo connection validated successfully',\n details: discovery\n ? {\n locales: discovery.locales.length,\n channels: discovery.channels.length,\n attributes: discovery.attributes.length,\n families: discovery.families.length,\n version: discovery.version,\n }\n : undefined,\n }\n } catch (error) {\n return {\n ok: false,\n message: error instanceof Error ? error.message : 'Akeneo validation failed',\n }\n }\n },\n\n async *streamImport(input): AsyncIterable<ImportBatch> {\n const entityType = assertEntityType(input.entityType)\n const mapping = normalizeAkeneoMapping(entityType, input.mapping as unknown as Record<string, unknown>)\n const client = createAkeneoClient(input.credentials)\n const importer = await createAkeneoImporter(client, input.scope)\n\n if (entityType === 'categories') {\n let batchIndex = 0\n let nextUrl = parseCursor(input.cursor)?.nextUrl ?? null\n const safeFullSync = !input.cursor\n const seenCategoryIds = new Set<string>()\n const reconciliation = buildDefaultReconciliationSettings()\n do {\n const page = await client.listCategories(nextUrl, input.batchSize)\n const items: ImportItem[] = []\n const locale = mapping.settings?.categories?.locale ?? 'en_US'\n for (const category of page.items) {\n seenCategoryIds.add(category.code)\n const result = await importer.upsertCategory(category, locale)\n items.push({\n externalId: category.code,\n data: {\n localId: result.localId,\n code: category.code,\n parent: category.parent ?? null,\n },\n action: result.action,\n })\n }\n nextUrl = page.nextUrl\n yield {\n items,\n cursor: buildListResumeCursor(nextUrl),\n hasMore: Boolean(nextUrl),\n totalEstimate: page.totalEstimate ?? undefined,\n processedCount: page.items.length,\n batchIndex,\n }\n batchIndex += 1\n } while (nextUrl)\n if (safeFullSync) {\n const locale = mapping.settings?.categories?.locale ?? 'en_US'\n await importer.reconcileCategories(seenCategoryIds, locale, reconciliation)\n }\n return\n }\n\n if (entityType === 'attributes') {\n const productMapping = await resolveMapping('products', input.scope)\n let batchIndex = 0\n let nextUrl = parseCursor(input.cursor)?.nextUrl ?? null\n const safeFullSync = !input.cursor\n const seenFamilyIds = new Set<string>()\n const reconciliation = buildDefaultReconciliationSettings()\n const locale = productMapping.settings?.products?.locale\n ?? mapping.settings?.categories?.locale\n ?? 'en_US'\n const customFieldItems = await importer.syncMappedCustomFields(productMapping, locale)\n const currentCustomFieldKeys = new Set(\n customFieldItems\n .map((item) => {\n const key = typeof item.data.key === 'string' ? item.data.key : null\n const target = item.data.target === 'variant' ? 'catalog:catalog_product_variant' : item.data.target === 'product' ? 'catalog:catalog_product' : null\n return key && target ? `${target}:${key}` : null\n })\n .filter((value): value is string => Boolean(value)),\n )\n do {\n const page = await client.listFamilies(nextUrl, input.batchSize)\n const items: ImportItem[] = []\n const includeTextAttributes = mapping.settings?.attributes?.includeTextAttributes ?? true\n const includeNumericAttributes = mapping.settings?.attributes?.includeNumericAttributes ?? true\n const familyFilter = mapping.settings?.attributes?.familyCodeFilter ?? []\n if (batchIndex === 0) {\n customFieldItems.forEach((item) => {\n items.push(item)\n })\n }\n for (const family of page.items) {\n if (familyFilter.length > 0 && !familyFilter.includes(family.code)) continue\n seenFamilyIds.add(family.code)\n const result = await importer.upsertAttributeFamily(\n family,\n locale,\n includeTextAttributes,\n includeNumericAttributes,\n )\n if (!result) continue\n items.push({\n externalId: family.code,\n data: {\n localId: result.localId,\n familyCode: family.code,\n },\n action: result.action,\n })\n }\n nextUrl = page.nextUrl\n yield {\n items,\n cursor: buildListResumeCursor(nextUrl),\n hasMore: Boolean(nextUrl),\n totalEstimate: page.totalEstimate ?? undefined,\n processedCount: page.items.length,\n batchIndex,\n }\n batchIndex += 1\n } while (nextUrl)\n if (safeFullSync) {\n await importer.reconcileMappedCustomFieldFieldsets(productMapping)\n await importer.reconcileAttributes({\n seenFamilyExternalIds: seenFamilyIds,\n currentCustomFieldKeys,\n reconciliation,\n })\n }\n return\n }\n\n let batchIndex = 0\n const currentCursor = parseCursor(input.cursor)\n let nextUrl = currentCursor?.nextUrl ?? null\n let updatedAfter = currentCursor?.updatedAfter ?? null\n let maxUpdatedAt = currentCursor?.maxUpdatedAt ?? updatedAfter\n const safeFullSync = !input.cursor\n const seenProductExternalIds = new Set<string>()\n const seenVariantExternalIds = new Set<string>()\n const reconciliation = mapping.settings?.products?.reconciliation ?? buildDefaultReconciliationSettings()\n\n do {\n const productPageSize = Math.min(Math.max(input.batchSize, 1), 10)\n const page = await client.listProducts({\n nextUrl,\n batchSize: productPageSize,\n updatedAfter,\n })\n\n const items: ImportItem[] = []\n for (const product of page.items) {\n try {\n const imported = await importer.upsertProduct(product, mapping)\n for (const item of imported) {\n if (item.data.localProductId) seenProductExternalIds.add(item.externalId)\n if (item.data.localVariantId) seenVariantExternalIds.add(item.externalId)\n items.push(item)\n }\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Akeneo product import failed'\n items.push({\n externalId: product.parent ? `${product.parent}:${product.uuid}` : product.uuid,\n action: 'failed',\n data: {\n errorMessage: message,\n sourceProductUuid: product.uuid,\n sourceIdentifier: product.identifier ?? null,\n sourceParentCode: product.parent ?? null,\n family: product.family ?? null,\n },\n })\n }\n if (typeof product.updated === 'string' && (!maxUpdatedAt || product.updated > maxUpdatedAt)) {\n maxUpdatedAt = product.updated\n }\n }\n\n nextUrl = page.nextUrl\n const nextCursor = nextUrl\n ? buildProductResumeCursor({\n updatedAfter,\n nextUrl,\n maxUpdatedAt,\n })\n : buildProductResumeCursor({\n updatedAfter: maxUpdatedAt ?? updatedAfter,\n nextUrl: null,\n maxUpdatedAt: null,\n })\n\n yield {\n items,\n cursor: nextCursor,\n hasMore: Boolean(nextUrl),\n totalEstimate: page.totalEstimate ?? undefined,\n processedCount: page.items.length,\n refreshCoverageEntityTypes: [\n 'catalog:catalog_product',\n 'catalog:catalog_product_variant',\n ],\n batchIndex,\n }\n batchIndex += 1\n\n if (!nextUrl && maxUpdatedAt) {\n updatedAfter = maxUpdatedAt\n }\n } while (nextUrl)\n\n if (safeFullSync) {\n yield {\n items: [],\n cursor: buildProductResumeCursor({\n updatedAfter: maxUpdatedAt ?? updatedAfter,\n nextUrl: null,\n maxUpdatedAt: null,\n }),\n hasMore: false,\n totalEstimate: undefined,\n processedCount: 0,\n message: 'Reconciling imported Akeneo products after the final batch',\n batchIndex,\n }\n await importer.reconcileMappedCustomFieldFieldsets(mapping)\n await importer.reconcileProducts(seenProductExternalIds, seenVariantExternalIds, reconciliation)\n }\n },\n}\n"],
5
+ "mappings": "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",
6
6
  "names": ["batchIndex", "nextUrl", "safeFullSync", "reconciliation"]
7
7
  }
package/jest.config.cjs CHANGED
@@ -18,12 +18,14 @@ module.exports = {
18
18
  {
19
19
  tsconfig: {
20
20
  jsx: 'react-jsx',
21
+ rootDir: '.',
22
+ ignoreDeprecations: '6.0',
21
23
  },
22
24
  },
23
25
  ],
24
26
  },
25
27
  transformIgnorePatterns: [
26
- 'node_modules/(?!(@mikro-orm)/)',
28
+ 'node_modules/(?!(@mikro-orm|kysely)/)',
27
29
  ],
28
30
  testMatch: ['<rootDir>/src/**/__tests__/**/*.test.(ts|tsx)'],
29
31
  passWithNoTests: true,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-mercato/sync-akeneo",
3
- "version": "0.6.2-develop.3467.1.2a1818709d",
3
+ "version": "0.6.2",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "scripts": {
@@ -52,18 +52,18 @@
52
52
  }
53
53
  },
54
54
  "dependencies": {
55
- "@open-mercato/core": "0.6.2-develop.3467.1.2a1818709d",
56
- "@open-mercato/ui": "0.6.2-develop.3467.1.2a1818709d",
55
+ "@open-mercato/core": "0.6.2",
56
+ "@open-mercato/ui": "0.6.2",
57
57
  "node-html-markdown": "^2.0.0"
58
58
  },
59
59
  "peerDependencies": {
60
60
  "@mikro-orm/postgresql": "^7.0.14",
61
- "@open-mercato/shared": "0.6.2-develop.3467.1.2a1818709d",
61
+ "@open-mercato/shared": "0.6.2",
62
62
  "react": "^19.0.0",
63
63
  "react-dom": "^19.0.0"
64
64
  },
65
65
  "devDependencies": {
66
- "@open-mercato/shared": "0.6.2-develop.3467.1.2a1818709d",
66
+ "@open-mercato/shared": "0.6.2",
67
67
  "@types/jest": "^30.0.0",
68
68
  "@types/react": "^19.2.14",
69
69
  "@types/react-dom": "^19.2.3",
@@ -81,6 +81,5 @@
81
81
  "type": "git",
82
82
  "url": "https://github.com/open-mercato/open-mercato",
83
83
  "directory": "packages/sync-akeneo"
84
- },
85
- "stableVersion": "0.6.1"
84
+ }
86
85
  }
@@ -1,5 +1,6 @@
1
1
  import { createRequestContainer } from '@open-mercato/shared/lib/di/container'
2
2
  import type { DataSyncAdapter, DataMapping, ImportBatch, ImportItem, ValidationResult } from '@open-mercato/core/modules/data_sync/lib/adapter'
3
+ import type { EntityManager } from '@mikro-orm/postgresql'
3
4
  import { buildListResumeCursor, buildProductResumeCursor, parseCursor } from './cursor'
4
5
  import { createAkeneoClient } from './client'
5
6
  import { createAkeneoImporter } from './catalog-importer'
@@ -15,7 +16,7 @@ function assertEntityType(entityType: string): AkeneoEntityType {
15
16
 
16
17
  async function resolveMapping(entityType: AkeneoEntityType, scope: { organizationId: string; tenantId: string }): Promise<AkeneoDataMapping> {
17
18
  const container = await createRequestContainer()
18
- const em = container.resolve('em')
19
+ const em = container.resolve('em') as EntityManager
19
20
  return loadAkeneoMapping(em, entityType, scope)
20
21
  }
21
22