- Shared types : ajout isCurrent sur ApiEntry et ApiEntryListItem - Backend entity : colonne is_current (boolean, default true) - Backend service : isCurrent calculé à la création, setCurrent() marque une version comme courante (siblings → false) - Backend controller : POST /api/apis/:id/set-current - Frontend ApiService : méthode setCurrent() - Browse/upload : affichage badge "Courante" via isCurrent - Seeder : données de démo mises à jour - Documentation : api-reference, architecture, local-setup, CLAUDE.md Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
875 lines
25 KiB
TypeScript
875 lines
25 KiB
TypeScript
import { Injectable, OnApplicationBootstrap } from '@nestjs/common';
|
|
import { InjectRepository } from '@nestjs/typeorm';
|
|
import { Repository, DataSource } from 'typeorm';
|
|
import * as fs from 'fs/promises';
|
|
import { ApiEntryEntity } from '../apis/api-entry.entity';
|
|
import { CategoryEntity } from '../categories/category.entity';
|
|
import { DocsGenerationService } from '../docs-generation/docs-generation.service';
|
|
|
|
/* ─── YAML demo data ─────────────────────────────────────────────────────── */
|
|
|
|
const PETSTORE_YAML = `openapi: "3.0.0"
|
|
info:
|
|
title: Swagger Petstore
|
|
description: A sample API that uses a petstore as an example to demonstrate features in the OpenAPI specification.
|
|
version: "3.0.4"
|
|
license:
|
|
name: Apache 2.0
|
|
servers:
|
|
- url: https://petstore.swagger.io/v3
|
|
paths:
|
|
/pets:
|
|
get:
|
|
summary: List all pets
|
|
operationId: listPets
|
|
tags: [pets]
|
|
parameters:
|
|
- name: limit
|
|
in: query
|
|
description: How many items to return at one time (max 100)
|
|
required: false
|
|
schema:
|
|
type: integer
|
|
format: int32
|
|
maximum: 100
|
|
responses:
|
|
"200":
|
|
description: A list of pets
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Pets"
|
|
default:
|
|
description: unexpected error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Error"
|
|
post:
|
|
summary: Create a pet
|
|
operationId: createPets
|
|
tags: [pets]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/NewPet"
|
|
responses:
|
|
"201":
|
|
description: Null response
|
|
default:
|
|
description: unexpected error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Error"
|
|
/pets/{petId}:
|
|
get:
|
|
summary: Info for a specific pet
|
|
operationId: showPetById
|
|
tags: [pets]
|
|
parameters:
|
|
- name: petId
|
|
in: path
|
|
required: true
|
|
description: The id of the pet to retrieve
|
|
schema:
|
|
type: string
|
|
responses:
|
|
"200":
|
|
description: Expected response to a valid request
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Pet"
|
|
default:
|
|
description: unexpected error
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Error"
|
|
components:
|
|
schemas:
|
|
Pet:
|
|
type: object
|
|
required: [id, name]
|
|
properties:
|
|
id:
|
|
type: integer
|
|
format: int64
|
|
name:
|
|
type: string
|
|
tag:
|
|
type: string
|
|
NewPet:
|
|
type: object
|
|
required: [name]
|
|
properties:
|
|
name:
|
|
type: string
|
|
tag:
|
|
type: string
|
|
Pets:
|
|
type: array
|
|
maxItems: 100
|
|
items:
|
|
$ref: "#/components/schemas/Pet"
|
|
Error:
|
|
type: object
|
|
required: [code, message]
|
|
properties:
|
|
code:
|
|
type: integer
|
|
format: int32
|
|
message:
|
|
type: string
|
|
`;
|
|
|
|
const STREETLIGHTS_YAML = `asyncapi: "3.0.0"
|
|
info:
|
|
title: Streetlights Kafka API
|
|
version: "1.0.0"
|
|
description: The Smartylighting Streetlights API allows you to remotely manage the city lights.
|
|
license:
|
|
name: Apache 2.0
|
|
servers:
|
|
scram-connections:
|
|
host: test.mykafkacluster.org:18092
|
|
protocol: kafka-secure
|
|
description: Test broker (SCRAM-SHA-512 security)
|
|
channels:
|
|
lightingMeasured:
|
|
address: "smartylighting.streetlights.1.0.event.{streetlightId}.lighting.measured"
|
|
messages:
|
|
lightMeasured:
|
|
$ref: "#/components/messages/LightMeasured"
|
|
parameters:
|
|
streetlightId:
|
|
$ref: "#/components/parameters/streetlightId"
|
|
lightTurnOn:
|
|
address: "smartylighting.streetlights.1.0.action.{streetlightId}.turn.on"
|
|
messages:
|
|
turnOn:
|
|
$ref: "#/components/messages/TurnOn"
|
|
parameters:
|
|
streetlightId:
|
|
$ref: "#/components/parameters/streetlightId"
|
|
lightTurnOff:
|
|
address: "smartylighting.streetlights.1.0.action.{streetlightId}.turn.off"
|
|
messages:
|
|
turnOff:
|
|
$ref: "#/components/messages/TurnOff"
|
|
parameters:
|
|
streetlightId:
|
|
$ref: "#/components/parameters/streetlightId"
|
|
operations:
|
|
receiveLightMeasurement:
|
|
action: receive
|
|
channel:
|
|
$ref: "#/channels/lightingMeasured"
|
|
messages:
|
|
- $ref: "#/channels/lightingMeasured/messages/lightMeasured"
|
|
turnOn:
|
|
action: send
|
|
channel:
|
|
$ref: "#/channels/lightTurnOn"
|
|
messages:
|
|
- $ref: "#/channels/lightTurnOn/messages/turnOn"
|
|
turnOff:
|
|
action: send
|
|
channel:
|
|
$ref: "#/channels/lightTurnOff"
|
|
messages:
|
|
- $ref: "#/channels/lightTurnOff/messages/turnOff"
|
|
components:
|
|
messages:
|
|
LightMeasured:
|
|
name: LightMeasured
|
|
title: Light measured
|
|
summary: Inform about environmental lighting conditions.
|
|
payload:
|
|
$ref: "#/components/schemas/LightMeasuredPayload"
|
|
TurnOn:
|
|
name: TurnOn
|
|
title: Turn on
|
|
summary: Command a specific streetlight to turn on.
|
|
payload:
|
|
$ref: "#/components/schemas/TurnOnPayload"
|
|
TurnOff:
|
|
name: TurnOff
|
|
title: Turn off
|
|
summary: Command a specific streetlight to turn off.
|
|
payload:
|
|
$ref: "#/components/schemas/TurnOffPayload"
|
|
parameters:
|
|
streetlightId:
|
|
description: The ID of the streetlight.
|
|
schemas:
|
|
LightMeasuredPayload:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
minimum: 0
|
|
description: ID of the streetlight.
|
|
lumens:
|
|
type: integer
|
|
minimum: 0
|
|
description: Light intensity measured in lumens.
|
|
sentAt:
|
|
type: string
|
|
format: date-time
|
|
TurnOnPayload:
|
|
type: object
|
|
properties:
|
|
command:
|
|
type: string
|
|
enum: [on]
|
|
sentAt:
|
|
type: string
|
|
format: date-time
|
|
TurnOffPayload:
|
|
type: object
|
|
properties:
|
|
command:
|
|
type: string
|
|
enum: [off]
|
|
sentAt:
|
|
type: string
|
|
format: date-time
|
|
`;
|
|
|
|
const ACCOUNT_SERVICE_YAML = `asyncapi: "3.0.0"
|
|
info:
|
|
title: Account Service
|
|
version: "1.0.0"
|
|
description: This service manages user accounts and publishes events on user lifecycle changes.
|
|
channels:
|
|
userSignedUp:
|
|
address: user/signedup
|
|
messages:
|
|
userSignedUp:
|
|
$ref: "#/components/messages/UserSignedUp"
|
|
userPasswordChanged:
|
|
address: user/passwordchanged
|
|
messages:
|
|
userPasswordChanged:
|
|
$ref: "#/components/messages/UserPasswordChanged"
|
|
operations:
|
|
sendUserSignedUp:
|
|
action: send
|
|
channel:
|
|
$ref: "#/channels/userSignedUp"
|
|
messages:
|
|
- $ref: "#/channels/userSignedUp/messages/userSignedUp"
|
|
sendUserPasswordChanged:
|
|
action: send
|
|
channel:
|
|
$ref: "#/channels/userPasswordChanged"
|
|
messages:
|
|
- $ref: "#/channels/userPasswordChanged/messages/userPasswordChanged"
|
|
components:
|
|
messages:
|
|
UserSignedUp:
|
|
payload:
|
|
$ref: "#/components/schemas/UserSignedUpPayload"
|
|
UserPasswordChanged:
|
|
payload:
|
|
$ref: "#/components/schemas/UserPasswordChangedPayload"
|
|
schemas:
|
|
UserSignedUpPayload:
|
|
type: object
|
|
properties:
|
|
displayName:
|
|
type: string
|
|
description: Name of the user
|
|
email:
|
|
type: string
|
|
format: email
|
|
description: Email of the user
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
UserPasswordChangedPayload:
|
|
type: object
|
|
properties:
|
|
userId:
|
|
type: string
|
|
changedAt:
|
|
type: string
|
|
format: date-time
|
|
`;
|
|
|
|
const ORDERS_YAML = `openapi: "3.0.0"
|
|
info:
|
|
title: Orders API
|
|
version: "1.0.0"
|
|
description: API de gestion des commandes clients.
|
|
servers:
|
|
- url: https://api.example.com/v1
|
|
paths:
|
|
/orders:
|
|
get:
|
|
summary: Lister les commandes
|
|
operationId: listOrders
|
|
tags: [orders]
|
|
parameters:
|
|
- name: status
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [pending, confirmed, shipped, delivered, cancelled]
|
|
- name: page
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 1
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 20
|
|
responses:
|
|
"200":
|
|
description: Liste des commandes
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/OrderList"
|
|
post:
|
|
summary: Créer une commande
|
|
operationId: createOrder
|
|
tags: [orders]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/CreateOrder"
|
|
responses:
|
|
"201":
|
|
description: Commande créée
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Order"
|
|
/orders/{orderId}:
|
|
get:
|
|
summary: Obtenir une commande
|
|
operationId: getOrder
|
|
tags: [orders]
|
|
parameters:
|
|
- name: orderId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
"200":
|
|
description: Détails de la commande
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Order"
|
|
"404":
|
|
description: Commande non trouvée
|
|
patch:
|
|
summary: Mettre à jour le statut
|
|
operationId: updateOrderStatus
|
|
tags: [orders]
|
|
parameters:
|
|
- name: orderId
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: string
|
|
requestBody:
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
status:
|
|
type: string
|
|
enum: [confirmed, shipped, delivered, cancelled]
|
|
responses:
|
|
"200":
|
|
description: Commande mise à jour
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/Order"
|
|
components:
|
|
schemas:
|
|
Order:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
customerId:
|
|
type: string
|
|
status:
|
|
type: string
|
|
enum: [pending, confirmed, shipped, delivered, cancelled]
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/OrderItem"
|
|
totalAmount:
|
|
type: number
|
|
format: float
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
OrderItem:
|
|
type: object
|
|
properties:
|
|
productId:
|
|
type: string
|
|
quantity:
|
|
type: integer
|
|
minimum: 1
|
|
price:
|
|
type: number
|
|
format: float
|
|
CreateOrder:
|
|
type: object
|
|
required: [customerId, items]
|
|
properties:
|
|
customerId:
|
|
type: string
|
|
items:
|
|
type: array
|
|
minItems: 1
|
|
items:
|
|
$ref: "#/components/schemas/OrderItem"
|
|
OrderList:
|
|
type: object
|
|
properties:
|
|
items:
|
|
type: array
|
|
items:
|
|
$ref: "#/components/schemas/Order"
|
|
total:
|
|
type: integer
|
|
page:
|
|
type: integer
|
|
limit:
|
|
type: integer
|
|
`;
|
|
|
|
const AUTH_YAML = `openapi: "3.0.0"
|
|
info:
|
|
title: Auth API
|
|
version: "1.0.0"
|
|
description: Service d'authentification et d'autorisation avec JWT.
|
|
servers:
|
|
- url: https://auth.example.com/v1
|
|
paths:
|
|
/auth/login:
|
|
post:
|
|
summary: Connexion
|
|
operationId: login
|
|
tags: [auth]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/LoginRequest"
|
|
responses:
|
|
"200":
|
|
description: Authentification réussie
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/TokenResponse"
|
|
"401":
|
|
description: Identifiants invalides
|
|
/auth/refresh:
|
|
post:
|
|
summary: Rafraîchir le token
|
|
operationId: refreshToken
|
|
tags: [auth]
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [refreshToken]
|
|
properties:
|
|
refreshToken:
|
|
type: string
|
|
responses:
|
|
"200":
|
|
description: Nouveau token émis
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/TokenResponse"
|
|
"401":
|
|
description: Refresh token invalide ou expiré
|
|
/auth/logout:
|
|
post:
|
|
summary: Déconnexion
|
|
operationId: logout
|
|
tags: [auth]
|
|
security:
|
|
- bearerAuth: []
|
|
responses:
|
|
"204":
|
|
description: Déconnecté avec succès
|
|
/users/me:
|
|
get:
|
|
summary: Profil utilisateur courant
|
|
operationId: getCurrentUser
|
|
tags: [users]
|
|
security:
|
|
- bearerAuth: []
|
|
responses:
|
|
"200":
|
|
description: Profil de l'utilisateur connecté
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: "#/components/schemas/User"
|
|
"401":
|
|
description: Non authentifié
|
|
components:
|
|
securitySchemes:
|
|
bearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: JWT
|
|
schemas:
|
|
LoginRequest:
|
|
type: object
|
|
required: [email, password]
|
|
properties:
|
|
email:
|
|
type: string
|
|
format: email
|
|
password:
|
|
type: string
|
|
format: password
|
|
TokenResponse:
|
|
type: object
|
|
properties:
|
|
accessToken:
|
|
type: string
|
|
refreshToken:
|
|
type: string
|
|
expiresIn:
|
|
type: integer
|
|
description: Durée de validité en secondes
|
|
User:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: string
|
|
email:
|
|
type: string
|
|
format: email
|
|
displayName:
|
|
type: string
|
|
roles:
|
|
type: array
|
|
items:
|
|
type: string
|
|
createdAt:
|
|
type: string
|
|
format: date-time
|
|
`;
|
|
|
|
/* ─── Seeder ──────────────────────────────────────────────────────────────── */
|
|
|
|
@Injectable()
|
|
export class SeederService implements OnApplicationBootstrap {
|
|
constructor(
|
|
@InjectRepository(ApiEntryEntity)
|
|
private readonly apiRepo: Repository<ApiEntryEntity>,
|
|
@InjectRepository(CategoryEntity)
|
|
private readonly categoryRepo: Repository<CategoryEntity>,
|
|
private readonly docsService: DocsGenerationService,
|
|
private readonly dataSource: DataSource,
|
|
) {}
|
|
|
|
async onApplicationBootstrap(): Promise<void> {
|
|
// Activer l'extension pg_trgm pour la recherche fuzzy
|
|
await this.dataSource.query('CREATE EXTENSION IF NOT EXISTS pg_trgm');
|
|
|
|
const forceReseed = process.env.FORCE_RESEED === 'true';
|
|
if (forceReseed) {
|
|
await this.reset();
|
|
}
|
|
const count = await this.apiRepo.count();
|
|
if (count > 0) {
|
|
await this.fixIsCurrentFlags();
|
|
return;
|
|
}
|
|
await this.seed();
|
|
}
|
|
|
|
/**
|
|
* Corrige les flags is_current après une migration :
|
|
* si toutes les versions d'un même groupe (name+convention) sont marquées courantes,
|
|
* on ne garde que la plus haute version.
|
|
*/
|
|
private async fixIsCurrentFlags(): Promise<void> {
|
|
await this.dataSource.query(`
|
|
UPDATE api_entries SET is_current = false
|
|
WHERE id IN (
|
|
SELECT a.id
|
|
FROM api_entries a
|
|
WHERE a.is_current = true
|
|
AND EXISTS (
|
|
SELECT 1 FROM api_entries b
|
|
WHERE b.name = a.name AND b.convention = a.convention
|
|
AND b.is_current = true
|
|
AND b.id != a.id
|
|
AND (
|
|
b.version_major > a.version_major
|
|
OR (b.version_major = a.version_major AND b.version_minor > a.version_minor)
|
|
OR (b.version_major = a.version_major AND b.version_minor = a.version_minor
|
|
AND b.version_patch > a.version_patch)
|
|
)
|
|
)
|
|
)
|
|
`);
|
|
}
|
|
|
|
private async reset(): Promise<void> {
|
|
/* Supprimer toutes les entrées puis les catégories */
|
|
await this.apiRepo.delete({});
|
|
await this.categoryRepo.delete({});
|
|
/* Nettoyer le répertoire docs-output */
|
|
const docsDir = process.env.DOCS_OUTPUT_DIR ?? '/app/docs-output';
|
|
await fs.rm(docsDir, { recursive: true, force: true });
|
|
await fs.mkdir(docsDir, { recursive: true });
|
|
console.log('[Seeder] Reset complet — données supprimées, docs nettoyées.');
|
|
}
|
|
|
|
private async seed(): Promise<void> {
|
|
/* Catégories racines */
|
|
const ecommerce = await this.categoryRepo.save(
|
|
this.categoryRepo.create({
|
|
name: 'E-commerce',
|
|
description: 'APIs liées au commerce électronique',
|
|
parentId: null,
|
|
orderIndex: 0,
|
|
}),
|
|
);
|
|
const infrastructure = await this.categoryRepo.save(
|
|
this.categoryRepo.create({
|
|
name: 'Infrastructure',
|
|
description: "APIs d'infrastructure et événements système",
|
|
parentId: null,
|
|
orderIndex: 1,
|
|
}),
|
|
);
|
|
const identite = await this.categoryRepo.save(
|
|
this.categoryRepo.create({
|
|
name: 'Identité & Accès',
|
|
description: "APIs d'authentification et contrôle d'accès",
|
|
parentId: null,
|
|
orderIndex: 2,
|
|
}),
|
|
);
|
|
|
|
/* Catégories feuilles */
|
|
const produits = await this.categoryRepo.save(
|
|
this.categoryRepo.create({
|
|
name: 'Produits',
|
|
description: 'Catalogue de produits',
|
|
parentId: ecommerce.id,
|
|
orderIndex: 0,
|
|
}),
|
|
);
|
|
const commandes = await this.categoryRepo.save(
|
|
this.categoryRepo.create({
|
|
name: 'Commandes',
|
|
description: 'Gestion des commandes',
|
|
parentId: ecommerce.id,
|
|
orderIndex: 1,
|
|
}),
|
|
);
|
|
const notifications = await this.categoryRepo.save(
|
|
this.categoryRepo.create({
|
|
name: 'Notifications',
|
|
description: 'Événements et notifications utilisateur',
|
|
parentId: ecommerce.id,
|
|
orderIndex: 2,
|
|
}),
|
|
);
|
|
const evenements = await this.categoryRepo.save(
|
|
this.categoryRepo.create({
|
|
name: 'Événements',
|
|
description: "Événements d'infrastructure temps réel",
|
|
parentId: infrastructure.id,
|
|
orderIndex: 0,
|
|
}),
|
|
);
|
|
const auth = await this.categoryRepo.save(
|
|
this.categoryRepo.create({
|
|
name: 'Authentification',
|
|
description: 'Authentification et autorisation',
|
|
parentId: identite.id,
|
|
orderIndex: 0,
|
|
}),
|
|
);
|
|
|
|
/* APIs de démo */
|
|
const entries = await this.apiRepo.save([
|
|
this.apiRepo.create({
|
|
convention: 'CONSULTER',
|
|
name: 'Référentiel Produits',
|
|
versionMajor: 3,
|
|
versionMinor: 0,
|
|
versionPatch: 4,
|
|
isCurrent: true,
|
|
description:
|
|
'A sample API that uses a petstore as an example to demonstrate features in the OpenAPI specification.',
|
|
type: 'OPENAPI',
|
|
yamlContent: PETSTORE_YAML,
|
|
status: 'PENDING',
|
|
categoryId: produits.id,
|
|
provider: 'DINUM',
|
|
contactFunctionalName: 'Alice Martin',
|
|
contactFunctionalEntity: 'Équipe Produit',
|
|
contactFunctionalEmail: 'alice.martin@example.gouv.fr',
|
|
contactTechnicalName: 'Bob Dupont',
|
|
contactTechnicalEntity: 'Équipe API',
|
|
contactTechnicalEmail: 'bob.dupont@example.gouv.fr',
|
|
}),
|
|
this.apiRepo.create({
|
|
convention: 'ETRE_NOTIFIE',
|
|
name: 'Éclairage Urbain Kafka',
|
|
versionMajor: 1,
|
|
versionMinor: 0,
|
|
versionPatch: 0,
|
|
description:
|
|
'The Smartylighting Streetlights API allows you to remotely manage the city lights using Kafka messaging.',
|
|
type: 'ASYNCAPI',
|
|
yamlContent: STREETLIGHTS_YAML,
|
|
status: 'PENDING',
|
|
categoryId: evenements.id,
|
|
provider: 'Bureau Infrastructure',
|
|
contactFunctionalName: 'Claire Leroy',
|
|
contactFunctionalEntity: 'Bureau Infrastructure',
|
|
contactFunctionalEmail: 'claire.leroy@example.gouv.fr',
|
|
contactTechnicalName: 'David Chen',
|
|
contactTechnicalEntity: 'Ops',
|
|
contactTechnicalEmail: 'ops@example.com',
|
|
}),
|
|
this.apiRepo.create({
|
|
convention: 'ETRE_NOTIFIE',
|
|
name: 'Comptes Utilisateurs',
|
|
versionMajor: 1,
|
|
versionMinor: 0,
|
|
versionPatch: 0,
|
|
description: "Service de gestion des comptes utilisateurs avec publication d'événements.",
|
|
type: 'ASYNCAPI',
|
|
yamlContent: ACCOUNT_SERVICE_YAML,
|
|
status: 'PENDING',
|
|
categoryId: notifications.id,
|
|
provider: 'Équipe Comptes',
|
|
contactFunctionalName: 'Emma Roux',
|
|
contactFunctionalEntity: 'Équipe Comptes',
|
|
contactFunctionalEmail: 'emma.roux@example.gouv.fr',
|
|
contactTechnicalName: 'François Blanc',
|
|
contactTechnicalEntity: 'Dev Core',
|
|
contactTechnicalEmail: 'dev-core@example.com',
|
|
}),
|
|
this.apiRepo.create({
|
|
convention: 'ENREGISTRER',
|
|
name: 'Commandes Clients',
|
|
versionMajor: 1,
|
|
versionMinor: 0,
|
|
versionPatch: 0,
|
|
description: 'API de gestion des commandes clients.',
|
|
type: 'OPENAPI',
|
|
yamlContent: ORDERS_YAML,
|
|
status: 'PENDING',
|
|
categoryId: commandes.id,
|
|
provider: 'Équipe Commerce',
|
|
contactFunctionalName: 'Gaëlle Moreau',
|
|
contactFunctionalEntity: 'Équipe Commerce',
|
|
contactFunctionalEmail: 'gaelle.moreau@example.gouv.fr',
|
|
contactTechnicalName: 'Hugo Simon',
|
|
contactTechnicalEntity: 'API Commerce',
|
|
contactTechnicalEmail: 'api-orders@example.com',
|
|
}),
|
|
this.apiRepo.create({
|
|
convention: 'CONSULTER',
|
|
name: 'Référentiel Produits',
|
|
versionMajor: 3,
|
|
versionMinor: 0,
|
|
versionPatch: 3,
|
|
isCurrent: false,
|
|
description:
|
|
'A sample API that uses a petstore as an example to demonstrate features in the OpenAPI specification.',
|
|
type: 'OPENAPI',
|
|
yamlContent: PETSTORE_YAML,
|
|
status: 'PENDING',
|
|
categoryId: produits.id,
|
|
provider: 'DINUM',
|
|
contactFunctionalName: 'Alice Martin',
|
|
contactFunctionalEntity: 'Équipe Produit',
|
|
contactFunctionalEmail: 'alice.martin@example.gouv.fr',
|
|
contactTechnicalName: 'Bob Dupont',
|
|
contactTechnicalEntity: 'Équipe API',
|
|
contactTechnicalEmail: 'bob.dupont@example.gouv.fr',
|
|
}),
|
|
this.apiRepo.create({
|
|
convention: 'CONSULTER',
|
|
name: 'Référentiel Produits',
|
|
versionMajor: 3,
|
|
versionMinor: 0,
|
|
versionPatch: 2,
|
|
isCurrent: false,
|
|
description:
|
|
'A sample API that uses a petstore as an example to demonstrate features in the OpenAPI specification.',
|
|
type: 'OPENAPI',
|
|
yamlContent: PETSTORE_YAML,
|
|
status: 'PENDING',
|
|
categoryId: produits.id,
|
|
provider: 'DINUM',
|
|
contactFunctionalName: 'Alice Martin',
|
|
contactFunctionalEntity: 'Équipe Produit',
|
|
contactFunctionalEmail: 'alice.martin@example.gouv.fr',
|
|
contactTechnicalName: 'Bob Dupont',
|
|
contactTechnicalEntity: 'Équipe API',
|
|
contactTechnicalEmail: 'bob.dupont@example.gouv.fr',
|
|
}),
|
|
this.apiRepo.create({
|
|
convention: 'CONSULTER',
|
|
name: 'Authentification JWT',
|
|
versionMajor: 1,
|
|
versionMinor: 0,
|
|
versionPatch: 0,
|
|
description: "Service d'authentification et d'autorisation.",
|
|
type: 'OPENAPI',
|
|
yamlContent: AUTH_YAML,
|
|
status: 'PENDING',
|
|
categoryId: auth.id,
|
|
provider: 'Équipe Sécurité',
|
|
contactFunctionalName: 'Isabelle Petit',
|
|
contactFunctionalEntity: 'Équipe Sécurité',
|
|
contactFunctionalEmail: 'isabelle.petit@example.gouv.fr',
|
|
contactTechnicalName: 'Julien Bernard',
|
|
contactTechnicalEntity: 'Sécurité SI',
|
|
contactTechnicalEmail: 'securite@example.com',
|
|
}),
|
|
]);
|
|
|
|
console.log('[Seeder] 8 catégories et 7 APIs de démo créées — génération docs en cours...');
|
|
|
|
/* Déclenche la génération de docs en fire-and-forget pour chaque API */
|
|
for (const entry of entries) {
|
|
this.docsService.generate(entry.id).catch(console.error);
|
|
}
|
|
}
|
|
}
|