# GraphQL API pour Vocabulaires RDF/OWL Verisav

API GraphQL permettant de requêter les vocabulaires RDF/OWL (DPP, RMA, WTY) en temps réel.

## Endpoint

```
POST /api/graphql
GET /api/graphql
```

**URL complète** : `https://www.verisav.fr/api/graphql`

**GraphiQL (développement)** : `http://localhost:3000/api/graphql` (si activé)

## Exemples de Requêtes

### 1. Lister tous les vocabulaires

```graphql
query {
  vocabularies {
    id
    name
    namespace
    version
    title(lang: "fr")
    description(lang: "fr")
    created
    modified
  }
}
```

### 2. Récupérer un vocabulaire spécifique

```graphql
query {
  vocabulary(id: "dpp") {
    id
    name
    namespace
    prefix
    version
    title(lang: "fr")
    description(lang: "en")
    created
    modified
    creator {
      type
      name
      seeAlso
    }
    publisher
    license
  }
}
```

### 3. Lister toutes les classes d'un vocabulaire

```graphql
query {
  classes(vocabularyId: "dpp") {
    name
    label(lang: "fr")
    comment(lang: "fr")
    subClassOf
    status
  }
}
```

### 4. Récupérer une classe spécifique

```graphql
query {
  class(vocabularyId: "dpp", name: "ProductPassport") {
    name
    label(lang: "fr")
    comment(lang: "en")
    subClassOf
    status
  }
}
```

### 5. Lister toutes les propriétés d'un vocabulaire

```graphql
query {
  properties(vocabularyId: "dpp") {
    name
    label(lang: "fr")
    comment(lang: "en")
    type
    domain
    range
    status
  }
}
```

### 6. Récupérer une propriété spécifique

```graphql
query {
  property(vocabularyId: "dpp", name: "hasWarranty") {
    name
    label(lang: "fr")
    comment(lang: "en")
    type
    domain
    range
    status
  }
}
```

### 7. Requête complète avec classes et propriétés

```graphql
query {
  vocabulary(id: "dpp") {
    id
    name
    version
    title(lang: "fr")
    description(lang: "fr")
    classes {
      name
      label(lang: "fr")
      comment(lang: "fr")
      subClassOf
    }
    properties {
      name
      label(lang: "fr")
      type
      domain
      range
    }
  }
}
```

### 8. Rechercher une propriété par nom (avec filtrage côté client)

```graphql
query {
  properties(vocabularyId: "dpp") {
    name
    label(lang: "en")
    type
    domain
    range
  }
}
```

Puis filtrer côté client pour trouver `hasWarranty`, `definesCoverage`, etc.

### 9. Récupérer les propriétés GS1 (DPP uniquement)

```graphql
query {
  properties(vocabularyId: "dpp") {
    name
    label(lang: "fr")
    comment(lang: "fr")
    type
    domain
    range
    status
  }
}
```

Filtrer pour trouver les propriétés GS1 :
- `gs1DigitalLink` - URI GS1 Digital Link
- `hasGln` - Global Location Number (GLN)
- `hasGtin` - Global Trade Item Number (GTIN)
- `granularityLevel` - Niveau de granularité (model/batch/serial)
- `batchLotNumber` - Numéro de lot (GS1 AI 10)
- `versionNumber` - Numéro de version GTIN (GS1 AI 22)

### 10. Récupérer les nouvelles classes GS1 (DPP uniquement)

```graphql
query {
  classes(vocabularyId: "dpp") {
    name
    label(lang: "fr")
    comment(lang: "fr")
    subClassOf
    status
  }
}
```

Nouvelles classes disponibles :
- `EconomicOperator` - Opérateur économique (fabricant, importateur, distributeur, etc.)
- `Facility` - Installation (usine, entrepôt, etc.)
- `CompoundIdentifier` - Identifiant composé (GTIN + variant/lot/série)

## Langues Supportées

Les champs `title`, `description`, `label`, et `comment` acceptent un paramètre `lang` :
- `en` (anglais) - par défaut
- `fr` (français)
- `de` (allemand)
- `it` (italien)
- `es` (espagnol)

Exemple :
```graphql
{
  vocabulary(id: "dpp") {
    title(lang: "fr")  # Retourne le titre en français
    title(lang: "en")  # Retourne le titre en anglais
  }
}
```

## Types GraphQL

### Vocabulary
- `id: String!` - Identifiant (dpp, rma, wty)
- `name: String!` - Nom du vocabulaire
- `namespace: String!` - URI du namespace
- `prefix: String!` - Préfixe recommandé
- `version: String!` - Version
- `title(lang: String): String` - Titre (multilingue)
- `description(lang: String): String` - Description (multilingue)
- `created: String!` - Date de création
- `modified: String!` - Date de modification
- `creator: Creator` - Créateur
- `publisher: String` - Éditeur
- `license: String` - Licence
- `classes: [Class!]!` - Liste des classes
- `properties: [Property!]!` - Liste des propriétés

### Class
- `name: String!` - Nom de la classe
- `label(lang: String): String` - Label (multilingue)
- `comment(lang: String): String` - Description (multilingue)
- `subClassOf: [String!]!` - Classes parentes
- `status: String` - Statut (stable, unstable, deprecated)

### Property
- `name: String!` - Nom de la propriété
- `label(lang: String): String` - Label (multilingue)
- `comment(lang: String): String` - Description (multilingue)
- `type: PropertyType!` - Type (OBJECT_PROPERTY ou DATATYPE_PROPERTY)
- `domain: [String!]!` - Domaines
- `range: [String!]!` - Ranges
- `status: String` - Statut (stable, unstable, deprecated)

## Performance

- **Cache en mémoire** : Les vocabulaires sont parsés une seule fois et mis en cache
- **Parsing lazy** : Les vocabulaires ne sont parsés que lorsqu'ils sont demandés
- **Réponses rapides** : < 50ms pour les requêtes après le premier parsing

## Utilisation avec cURL

```bash
# Requête simple
curl -X POST https://www.verisav.fr/api/graphql \
  -H "Content-Type: application/json" \
  -d '{
    "query": "{ vocabularies { id name version } }"
  }'
```

## Utilisation avec fetch (JavaScript)

```javascript
const response = await fetch('https://www.verisav.fr/api/graphql', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify({
    query: `
      query {
        vocabulary(id: "dpp") {
          name
          classes {
            name
            label(lang: "fr")
          }
        }
      }
    `
  })
})

const { data } = await response.json()
console.log(data)
```

## Introspection

L'API supporte l'introspection GraphQL standard. Vous pouvez utiliser GraphiQL ou un outil comme [GraphQL Playground](https://github.com/graphql/graphql-playground) pour explorer le schema.

Pour activer GraphiQL en production, définissez la variable d'environnement `ENABLE_GRAPHIQL=true`.

## Vocabulaires Disponibles

- **dpp** : Digital Product Passport Vocabulary
  - Aligné avec GS1 Digital Link et ESPR (EU 2024/1781)
  - Support GTIN, GLN, granularité (model/batch/serial)
  - Classes : ProductPassport, EconomicOperator, Facility, CompoundIdentifier, etc.
  - Propriétés GS1 : gs1DigitalLink, hasGln, hasGtin, granularityLevel, batchLotNumber, versionNumber
- **rma** : Return Merchandise Authorization Vocabulary
  - Gestion des retours et tickets SAV
  - Classes : ReturnRequest, Ticket, Dispute, Resolution, etc.
- **wty** : Warranty & Contracts Vocabulary
  - Garanties et contrats lisibles par machine
  - Classes : Warranty, Contract, Coverage, PaymentRule, etc.

## Autres APIs Disponibles

En plus de l'API GraphQL, vous pouvez accéder aux vocabulaires via :

1. **APIs REST individuelles** :
   - JSON-LD : `https://www.verisav.fr/api/{vocab}/{vocab}.jsonld`
   - Exemple : `https://www.verisav.fr/api/dpp/dpp.jsonld`
   - Alternative (fichiers statiques) : `https://ns.verisav.fr/{vocab}/{vocab}.jsonld`

2. **API REST de recherche** :
   - `https://www.verisav.fr/api/v1/vocabulary/{vocab}/search?q={query}`
   - Exemple : `https://www.verisav.fr/api/v1/vocabulary/dpp/search?q=ProductPassport`

3. **Fichiers statiques** :
   - Turtle : `https://ns.verisav.fr/{vocab}/{vocab}.ttl`
   - JSON-LD : `https://ns.verisav.fr/{vocab}/{vocab}.jsonld`
   - RDF/XML : `https://ns.verisav.fr/{vocab}/{vocab}.xml` (DPP uniquement)
   - Documentation HTML : `https://ns.verisav.fr/{vocab}/` ou `https://www.verisav.fr/{vocab}/`

## Alignement GS1 et ESPR (DPP uniquement)

Le vocabulaire DPP est aligné avec :
- **GS1 Digital Link** : Standard pour les identifiants produits
- **ESPR (EU 2024/1781)** : Réglementation européenne sur l'écoconception
- **GTIN** : Global Trade Item Number (GTIN-8/12/13/14)
- **GLN** : Global Location Number pour organisations et installations
- **Granularité** : Support des niveaux model, batch, et serial

### Exemple : Requête pour les propriétés GS1

```graphql
query {
  property(vocabularyId: "dpp", name: "gs1DigitalLink") {
    name
    label(lang: "fr")
    comment(lang: "fr")
    type
    domain
    range
    status
  }
}
```

### Exemple : Requête pour les classes GS1

```graphql
query {
  class(vocabularyId: "dpp", name: "EconomicOperator") {
    name
    label(lang: "fr")
    comment(lang: "fr")
    subClassOf
    status
  }
}
```

