@shopimind/sdk-shopimind
v1.0.1
Published
Official JavaScript/TypeScript SDK for the Shopimind API. Mirrors the PHP SDK (shopimind/sdk-shopimind) feature-for-feature.
Readme
@shopimind/sdk-shopimind
SDK officiel JavaScript / TypeScript pour l'API Shopimind.
- Node.js ≥ 14
- CommonJS (
require) et ESM / TypeScript (import) - Types
.d.tsinclus - Dépendance runtime unique :
axios - Retry automatique, chunking optionnel, format de retour uniforme (envelope)
Installation
Via registre npm
yarn add @shopimind/sdk-shopimindnpm install @shopimind/sdk-shopimindPour un registre privé (GitHub Packages, Verdaccio, Nexus), configurer le scope dans le .npmrc du projet :
@shopimind:registry=https://npm.pkg.github.com
//npm.pkg.github.com/:_authToken=${GITHUB_TOKEN}Via Git
yarn add git+https://github.com/shopimind/shopimind-api-js-sdk.git#v1.0.1Via chemin local
yarn add file:../shopimind-api-js-sdkQuick start
const { SpmClient, SpmCustomers } = require('@shopimind/sdk-shopimind');
const client = SpmClient.getClient('v1', process.env.SHOPIMIND_API_KEY);
const res = await SpmCustomers.bulkSave(client, customers, { chunk: true });
if (!res.ok) {
console.error('Sync failed', res.error);
return;
}
console.log(`Synced ${res.data.sent_count}, rejected ${res.data.rejected_count}`);Format de réponse — envelope uniforme
Toutes les méthodes retournent le même shape, succès ou échec. Le SDK ne throw jamais pour une erreur HTTP.
{
ok: true | false,
statusCode: 200 | 4xx | 5xx | 0,
data: {/* body de l'API */} | null,
error: null | {
message: string,
code: string, // 'HTTP_503', 'ETIMEDOUT', etc.
retryable: boolean,
attempts: number, // combien de tentatives effectuées
details?: any, // pour les aggregated errors (chunk failures)
},
}const res = await SpmCustomers.bulkSave(client, items);
if (res.ok) {
console.log(res.data.sent_count, res.data.rejected_count);
} else {
if (res.error.retryable) {
console.warn('Transient failure, API is unavailable');
} else {
console.error('Permanent failure', res.error.message);
}
}Retry automatique
Par défaut, le SDK retry 3 fois sur :
- HTTP
408,429,500,502,503,504 - Erreurs réseau :
ECONNRESET,ETIMEDOUT,ECONNREFUSED,ENETUNREACH,ENOTFOUND,EAI_AGAIN
Avec un backoff exponentiel (1s → 2s → 4s avec jitter ±500ms, cap à 10s).
Configuration au niveau client
const client = SpmClient.getClient('v1', apiKey, {
retry: {
maxRetries: 5,
backoffBaseMs: 2000,
backoffCapMs: 30000,
retryableStatus: [429, 502, 503, 504],
},
});Désactiver les retries
const client = SpmClient.getClient('v1', apiKey, { retry: false });Chunking optionnel
Passe un gros tableau au SDK, il le découpe tout seul en batches alignés sur la limite de l'API et agrège les résultats.
const hugeArray = Array(500).fill().map((_, i) => ({ /* customer data */ }));
const res = await SpmCustomers.bulkSave(client, hugeArray, { chunk: true });
console.log(res.data.sent_count); // total agrégé
console.log(res.data.chunks); // détail par chunk (10 × 50)Par défaut, chunkSize vaut la valeur alignée sur l'API NestJS :
| Ressource | CHUNK_SIZE |
|---|---|
| SpmCustomers, SpmCustomersAddresses, SpmProducts, SpmProductsImages, SpmProductsVariations, SpmOrders, SpmVouchers | 50 |
| SpmCustomersGroups, SpmProductsCategories, SpmProductsManufacturers, SpmOrdersCarriers, SpmOrdersStatuses, SpmNewsletterSubscribers | 100 |
Override si besoin :
await SpmProducts.bulkSave(client, items, { chunk: true, chunkSize: 25 });Accès direct à la constante :
console.log(SpmCustomers.CHUNK_SIZE); // 50Helpers partagés
const { SpmHelpers } = require('@shopimind/sdk-shopimind');
SpmHelpers.chunk(array, 50);
// → [[...50], [...50], ...]
SpmHelpers.mergeResponses([envelope1, envelope2, ...]);
// → envelope agrégée avec data.sent_count, data.rejected_count, data.chunks[]
SpmHelpers.extractCounts(envelope);
// → { sent: N, rejected: M, failed: K }
SpmHelpers.isRetryable(error);
// → true si l'erreur ou l'envelope est retryable (429 / 5xx / network)
SpmHelpers.formatError(envelope);
// → { message, code, statusCode, retryable, attempts, details }
// safe à sérialiser pour des logs structurésConfiguration du client — toutes les options
const client = SpmClient.getClient('v1', 'your-api-key', {
baseUrl: 'https://core-staging.shopimind.com',
headers: { 'x-trace-id': 'abc-123' },
timeout: 60000,
labelSource: 'web',
retry: { maxRetries: 3 },
});| Option | Type | Défaut | Rôle |
|---|---|---|---|
| baseUrl | string | https://core.shopimind.com | URL de base de l'API |
| headers | Record<string, string> | {} | Headers additionnels |
| timeout | number | 30000 | Timeout de requête (ms) |
| labelSource | string \| null | 'web' | Injecté en label_source dans les POST/PUT. null désactive. |
| retry | SpmRetryOptions \| false | Voir Retry automatique | Politique de retry |
L'URL de base peut aussi être surchargée via la variable d'environnement SHOPIMIND_CORE_API_BASE. Priorité : options.baseUrl > SHOPIMIND_CORE_API_BASE > défaut.
Headers nécessaires pour shop/connection
L'endpoint POST /shop/connection attend trois headers spécifiques : client-id, client-version, current-build. Les passer via options.headers :
const client = SpmClient.getClient('v1', apiKey, {
headers: {
'client-id': clientId,
'client-version': '5.0.0',
'current-build': '1',
},
});Enregistrer une shop
const { SpmShopConnection } = require('@shopimind/sdk-shopimind');
const res = await SpmShopConnection.saveConfiguration(client, {
default_currency: 'EUR',
default_lang: 'fr',
langs: ['fr', 'en'],
timezone: 'Europe/Paris',
url_client: 'https://myshop.example.com',
ecommerce_version: '2.7.0',
module_version: '5.0.0',
});Valider un webhook Shopimind entrant
const { SpmRequestValidator } = require('@shopimind/sdk-shopimind');
const validation = SpmRequestValidator.validateRequest({
clientId: req.headers['shopimind-client-identifiant'],
hmacToken: req.headers['shopimind-token'],
body: req.body,
apiIdentification: config.apiIdentification,
apiPassword: config.apiPassword,
});
if (!validation.valid) {
return res.status(401).json({ error: validation.error });
}Pattern d'utilisation des ressources
Instance — pour manipuler un item à la fois
const { SpmCustomers } = require('@shopimind/sdk-shopimind');
const customer = new SpmCustomers(client);
customer.customer_id = 'cust_1';
customer.email = '[email protected]';
customer.first_name = 'Foo';
customer.last_name = 'Bar';
customer.is_opt_in = true;
customer.is_newsletter_subscribed = false;
customer.lang = 'fr';
customer.is_active = true;
customer.created_at = '2026-01-01T00:00:00Z';
customer.updated_at = '2026-01-01T00:00:00Z';
const res = await customer.save();Statique — pour les opérations bulk
await SpmCustomers.bulkSave(client, items, { chunk: true });
await SpmCustomers.bulkUpdate(client, items, { chunk: true });
await SpmCustomers.delete(client, 'cust_1');
await SpmCustomers.bulkDelete(client, ['cust_1', 'cust_2']);Ressources imbriquées (addresses, images, variations)
Le constructeur prend le parent. Les méthodes statiques bulkSave prennent le parent en 2e argument :
const { SpmCustomersAddresses } = require('@shopimind/sdk-shopimind');
await SpmCustomersAddresses.bulkSave(client, 'cust_1', addresses, { chunk: true });
await SpmCustomersAddresses.bulkDelete(client, 'cust_1', [42, 43]);Endpoint flat bulkSaveAll
Payload plat avec le parent embarqué dans chaque item. Utile pour un batch multi-parents :
await SpmCustomersAddresses.bulkSaveAll(client, [
{ customer_id: 'cust_1', address_id: 1, /* ... */ },
{ customer_id: 'cust_2', address_id: 2, /* ... */ },
], { chunk: true });Ressources disponibles
| Export | Endpoint | Méthodes |
|---|---|---|
| SpmShopConnection | shop/connection | saveConfiguration |
| SpmCustomers | customers | CRUD + bulk |
| SpmCustomersAddresses | customers/:id/addresses + customers/addresses/bulk | CRUD + bulk + bulkSaveAll |
| SpmCustomersGroups | customers-groups | CRUD + bulk |
| SpmProducts | products | CRUD + bulk |
| SpmProductsCategories | products-categories | CRUD + bulk |
| SpmProductsImages | products/:id/images + products/images/bulk | CRUD + bulk + bulkSaveAll |
| SpmProductsManufacturers | products-manufacturers | CRUD + bulk |
| SpmProductsVariations | products/:id/variations + products/variations/bulk | CRUD + bulk + bulkSaveAll |
| SpmOrders | orders | CRUD + bulk |
| SpmOrdersCarriers | orders-carriers | CRUD + bulk |
| SpmOrdersStatuses | orders-statuses | CRUD + bulk |
| SpmNewsletterSubscribers | newsletter-subscribers | bulk uniquement (pas de delete côté API) |
| SpmVouchers | vouchers | CRUD + bulk |
Associer un data_source
Toutes les ressources acceptent optionnellement un identifiant ou libellé de source de données :
customer.id_data_source = 3;
customer.source_label = 'Magasin Paris';
await customer.save();TypeScript
Les types sont dans index.d.ts et importables directement :
import {
SpmClient,
SpmCustomers,
SpmCustomerData,
SpmEnvelope,
SpmChunkedEnvelope,
SpmHelpers,
} from '@shopimind/sdk-shopimind';
const client = SpmClient.getClient('v1', process.env.SHOPIMIND_API_KEY!);
const items: SpmCustomerData[] = [/* ... */];
const res: SpmEnvelope | SpmChunkedEnvelope = await SpmCustomers.bulkSave(client, items, { chunk: true });
if (res.ok) {
const counts = SpmHelpers.extractCounts(res);
console.log(`${counts.sent} envoyés, ${counts.rejected} rejetés`);
}Interfaces data disponibles : SpmCustomerData, SpmCustomerAddressData, SpmBulkCustomerAddressData, SpmCustomerGroupData, SpmProductData, SpmProductCategoryData, SpmProductImageData, SpmBulkProductImageData, SpmProductManufacturerData, SpmProductVariationData, SpmBulkProductVariationData, SpmOrderData, SpmOrderProduct, SpmOrderCustomer, SpmOrderCarrierData, SpmOrderStatusData, SpmNewsletterSubscriberData, SpmVoucherData, SpmShopConnectionData, SpmEnvelope, SpmChunkedEnvelope, SpmBulkOptions, SpmRetryOptions.
License
Propriétaire — Shopimind.
