Démarrage rapide
Cette page vous guide dans la construction d'une intégration ShopiMind minimale mais réelle, depuis un projet vide jusqu'au manifeste que vous soumettez pour l'enregistrement. Le chemin est volontairement aussi court que possible : vous installez le kit et le SDK, vous écrivez un squelette d'intégration, vous l'exécutez localement, puis vous générez son manifeste.
Vous écrivez un defineIntegration({...}) ; le kit d'intégration JavaScript (@shopimind/integration-kit-js) fait le reste : serveur de webhooks, vérification de signature, planificateur de synchronisation, un store local (une base de données SQLite, à l'intérieur de votre service) et un client HTTP ShopiMind authentifié et prêt à l'emploi sur ctx.spm.
Le kit dépend du SDK et le ré-exporte (@shopimind/sdk-js) : vous importez les ressources et les types du SDK depuis le kit, et vous appelez les méthodes statiques du SDK sur ctx.spm pour pousser vos données.
Avant de commencer
- Node.js 18+ (les deux paquets sont ESM uniquement, Node ≥ 18.17).
- Quelques connaissances en TypeScript. Tout le code de cette page est en TypeScript.
- Aucun identifiant ShopiMind n'est requis pour ce premier parcours : vous exécutez l'intégration localement et générez son manifeste hors ligne.
1. Créer le projet
Créez un dossier, initialisez package.json, puis ajoutez TypeScript :
mkdir my-app && cd my-app
yarn init -y
yarn add -D typescript @types/nodeComme le kit et le SDK sont ESM uniquement, votre projet doit l'être aussi. Dans package.json, déclarez "type": "module" et un script de build :
{
"name": "my-app",
"type": "module",
"scripts": {
"build": "tsc -b",
"start": "node dist/main.js",
"print:manifest": "node dist/print-manifest.js"
}
}Un tsconfig.json minimal qui émet de l'ESM moderne dans dist/ :
{
"compilerOptions": {
"target": "ES2022",
"module": "NodeNext",
"moduleResolution": "NodeNext",
"outDir": "dist",
"rootDir": "src",
"strict": true
},
"include": ["src"]
}2. Installer le kit, le SDK et dotenv
yarn add @shopimind/integration-kit-js @shopimind/sdk-js dotenv| Paquet | Rôle |
|---|---|
@shopimind/integration-kit-js | Le runtime d'intégration (^1.6.0) : serveur de webhooks, signature HMAC, planificateur, store SQLite, dispatch du cycle de vie. Il dépend du SDK et le ré-exporte. |
@shopimind/sdk-js | Le client HTTP sortant vers l'API ShopiMind (en-tête spm-api-key). Le kit construit le client pour vous et l'expose sur ctx.spm ; vous appelez les méthodes statiques du SDK dessus. |
dotenv | Charge votre fichier .env dans process.env au démarrage. |
Importez le SDK depuis le kit
Parce que le kit ré-exporte le SDK (export * from '@shopimind/sdk-js'), importez les ressources et les types du SDK — SpmCustomers, SpmEvents, SpmHelpers, … — directement depuis @shopimind/integration-kit-js. Vous n'instanciez jamais le SDK vous-même.
3. Écrire l'intégration (src/integration.ts)
L'intégration est le cœur de votre projet. Vous la déclarez avec defineIntegration ; le kit valide sa forme au démarrage (slug valide, pas d'entité de synchronisation en double…).
Commencez par typer vos réglages dans src/settings.ts :
// src/settings.ts
import type { RawConfigs } from '@shopimind/integration-kit-js';
export interface MySettings {
apiKey: string;
}
export function parseSettings(raw: RawConfigs): MySettings {
return { apiKey: String(raw.api_key ?? '') };
}Puis l'intégration elle-même. Voici un squelette minimal — chaque champ optionnel (provisioning, widgets, remoteData, hooks) sera détaillé dans les pages suivantes :
// src/integration.ts
import { defineIntegration } from '@shopimind/integration-kit-js';
import type { Integration, IntegrationContext } from '@shopimind/integration-kit-js';
import type { MySettings } from './settings.js';
import { parseSettings } from './settings.js';
export const myIntegration: Integration<MySettings> = defineIntegration({
slug: 'my-app', // ^[a-z0-9_-]+$
meta: {
name: 'My App',
version: '1.0.0',
categories: ['crm'], // neutral slugs, resolved at registration
},
configSchema: {
steps: [
{
key: 'connection',
label: { fr: 'Connexion', en: 'Connection' },
fields: [
{
key: 'api_key',
type: 'password',
required: true,
sensitive: true,
label: { fr: 'Clé API', en: 'API key' },
},
],
on_complete: { action: 'test_connection' },
},
],
},
parseSettings,
testConnection: async (ctx: IntegrationContext<MySettings>) => Boolean(ctx.settings.apiKey),
syncSteps: [], // your sync steps — see data-sync
});À garder à l'esprit
installationId(dansctx) est un jeton opaque émis par ShopiMind : ne l'interprétez jamais.- Vous poussez vos données via
ctx.spm— unSpmHttpClientbrut, déjà authentifié. Vous appelez les méthodes statiques du SDK dessus, par exempleSpmCustomers.bulkSave(ctx.spm, items, { chunk: true })ouSpmEvents.trigger(ctx.spm, codeName, payload). Dans une étape de synchronisation, préférez le helper de push sûrctx.sendBulk(...)— voir Synchroniser vos données.
4. Câbler le runtime (src/main.ts)
Le point d'entrée mappe vos variables d'environnement vers les options du kit, puis démarre le serveur. Le kit construit lui-même le client HTTP ShopiMind — vous n'instanciez pas le SDK et il n'y a aucune passerelle à câbler.
// src/main.ts
import 'dotenv/config';
import { createIntegrationApp } from '@shopimind/integration-kit-js';
import { myIntegration } from './integration.js';
const env = process.env;
const required = (key: string): string => {
const v = env[key];
if (!v) throw new Error(`Required environment variable: ${key}`);
return v;
};
const app = createIntegrationApp(myIntegration, {
databasePath: env.DATABASE_PATH ?? './data/store.sqlite',
webhookSecret: required('WEBHOOK_SECRET'),
credentialsKey: env.CREDENTIALS_KEY ?? undefined,
allowPlaintextSecrets: env.NODE_ENV !== 'production', // dev only; prod requires CREDENTIALS_KEY
adminToken: env.ADMIN_TOKEN ?? undefined,
backfillDays: env.BACKFILL_DAYS ? Number(env.BACKFILL_DAYS) : 365,
syncIntervalMinutes: env.SYNC_INTERVAL_MINUTES ? Number(env.SYNC_INTERVAL_MINUTES) : 15,
port: env.PORT ? Number(env.PORT) : 8080,
...(env.SHOPIMIND_API_URL ? { spmBaseUrl: env.SHOPIMIND_API_URL } : {}),
});
void app.start().catch((e: unknown) => {
console.error('Integration startup failed', e);
process.exit(1);
});
process.on('SIGTERM', () => void app.stop().then(() => process.exit(0)));
process.on('SIGINT', () => void app.stop().then(() => process.exit(0)));createIntegrationApp construit le SpmHttpClient authentifié et l'expose sur ctx.spm. La base de l'API ShopiMind par défaut est https://core.shopimind.com ; passez spmBaseUrl (ici depuis SHOPIMIND_API_URL) pour la surcharger.
ctx.spm est le client SDK brut
ctx.spm est un simple SpmHttpClient ; vous le pilotez avec les méthodes statiques du SDK, toutes ré-exportées par le kit. Le SDK ne lève jamais d'exception sur une erreur HTTP — il retourne une enveloppe { ok, statusCode, data, error }. Utilisez SpmHelpers.unwrapOrThrow(env) ou SpmHelpers.extractCounts(env) pour la traiter.
Variables d'environnement (.env)
Créez un fichier .env à la racine de l'intégration :
WEBHOOK_SECRET= # HMAC, provided by ShopiMind at registration (required)
CREDENTIALS_KEY= # AES-256 (64 hex) — encryption of secrets at rest; REQUIRED in production
ADMIN_TOKEN= # protects the /admin/* routes
PORT=8080
SYNC_INTERVAL_MINUTES=15
BACKFILL_DAYS=365
SHOPIMIND_API_URL= # overrides the API base (default https://core.shopimind.com)
DATABASE_PATH=./data/store.sqlitePour cette première exécution
WEBHOOK_SECRET est requis : sans lui, l'intégration ne démarre pas. Vous le recevrez à l'enregistrement (voir l'étape 6). Pour démarrer localement dès maintenant, mettez-y n'importe quelle valeur non vide ; les webhooks réellement signés par ShopiMind ne seront acceptés qu'avec le vrai secret. En production, CREDENTIALS_KEY (64 hex) devient requis — sinon l'intégration refuse de démarrer (fail-closed). Ne définissez allowPlaintextSecrets: true que pour le développement local.
5. Exécuter localement
Buildez, puis démarrez :
yarn build
yarn startLe serveur écoute sur le port 8080 par défaut. Vérifiez qu'il est vivant via la sonde de liveness /health (sans authentification) :
curl http://localhost:8080/health
# → {"status":"ok"}Le kit expose plusieurs routes HTTP. Vous n'avez rien à coder côté serveur : il les sert pour vous.
| Méthode | Chemin | Rôle |
|---|---|---|
POST | /webhook/receive | Tous les événements du cycle de vie (signés HMAC) |
POST | /webhook/test-connection | Test de connexion depuis l'UI ShopiMind (signé HMAC) |
POST | /webhook/remote-data/{resource} | Options dynamiques d'un select (signé HMAC) |
GET | /health | Sonde de liveness |
La vérification de la signature HMAC X-Shopimind-Signature des webhooks entrants est effectuée automatiquement par le kit. Vous n'avez aucune validation de signature à écrire.
6. Générer le manifeste
Le manifeste est un JSON neutre qui décrit votre intégration (slug, config, widgets, webhooks relatifs, événements du cycle de vie). C'est ce que vous soumettez à ShopiMind pour l'enregistrement — il ne contient aucun SQL, aucun secret, aucune URL absolue.
Ajoutez un petit script src/print-manifest.ts :
// src/print-manifest.ts
import { buildIntegrationManifest } from '@shopimind/integration-kit-js';
import { myIntegration } from './integration.js';
console.log(JSON.stringify(buildIntegrationManifest(myIntegration), null, 2));Le script print:manifest (déclaré à l'étape 1) le compile et l'exécute. Redirigez la sortie vers un fichier :
yarn build
yarn print:manifest > integration.manifest.jsonEnvoyez ce fichier à dev@shopimind.com pour l'enregistrement. ShopiMind génère ensuite le webhook_secret (à placer dans WEBHOOK_SECRET), résout vos catégories et finalise l'enregistrement.
Votre intégration tourne
Vous avez une intégration qui démarre, répond sur /health, expose ses webhooks signés et produit son manifeste. Elle ne pousse encore aucune donnée : c'est l'objet des étapes suivantes.
Et ensuite
- → Le kit en détail — le contrat complet de
defineIntegration, l'IntegrationContext, les options decreateIntegrationAppet le store. - → Configuration — étapes, champs, options dynamiques (
remote),sensitiveettest_connection. - → Synchroniser vos données — déclarez des
SyncStep, gérez le curseur et poussez en toute sécurité viactx.sendBulket les statiques du SDK surctx.spm. - → SDK JavaScript — la référence du client HTTP sortant.