一键导入
masa-provider
Creates new functionalities that fetch reference data via MasaProvider instead of directly using LanceleauGateway or RoseauGateway.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
菜单
Creates new functionalities that fetch reference data via MasaProvider instead of directly using LanceleauGateway or RoseauGateway.
用 Codex 或 Claude 帮你安装 复制这段 Prompt,粘贴到 Codex、Claude 或其他助手里,让它检查 Skill 页面并帮你完成安装。
基于 SOC 职业分类
Extracts methods from the monolithic RoseauGateway/RoseauRepository into a dedicated gateway/repository pair within the same folder. Use this when moving domain-specific methods out of roseau.gateway into their own gateway.
Creates a full-stack paginated table page with filters, sorting, and detail view — from SQL to React — using MasaProvider.
Creates unit and e2e tests for NestJS applications using Jest and Supertest. Includes patterns for testing services, controllers, guards, and e2e tests with testcontainers.
Creates a typed API endpoint across shared route definition, NestJS controller, frontend service, and Query hook.
Creates unit tests for React frontend components using Vitest and React Testing Library, following accessibility-first best practices.
Develops, styles, and tests DSFR-compliant React 19 components.
| name | masa-provider |
| description | Creates new functionalities that fetch reference data via MasaProvider instead of directly using LanceleauGateway or RoseauGateway. |
Use MasaProvider for all new code that needs reference live data (STEU, ITV, PMO, SCL, droits, auth...). Never inject LanceleauGateway or RoseauGateway directly in domain services.
MasaProvider is an anti-corruption layer / facade that centralizes every call to reference data currently stored in the lanceleau.* and roseau.* PostgreSQL schemas.
Some methods of these two databases will be replaced by a MASA REST API in the near future. When that happens, only MasaProvider internals need to change -- every consumer stays untouched.
┌──────────────────┐ ┌──────────────────┐ ┌─────────────────────┐
│ Domain Service │─────>│ MasaProvider │─────>│ Roseau / Lanceleau │
│ (your code) │ │ (facade) │ │ (will become HTTP) │
└──────────────────┘ └──────────────────┘ └─────────────────────┘
▲
│ Only this layer changes
│ when MASA REST API ships
| DO | DON'T |
|---|---|
Inject MasaProvider in domain services | Inject RoseauGateway or LanceleauGateway in domain services |
Import from @masa/masa.provider | Import from @referentiel/roseau/* or @referentiel/lanceleau/* in domain code |
Add new methods to MasaProvider when you need new data | Query roseau/lanceleau repositories directly |
| Keep MasaProvider methods as pure pass-through (no business logic) | Add mapping, filtering, or business rules inside MasaProvider |
Define return types in @masa/masa.dto.ts | Re-use entity types from @referentiel/ in domain code |
apps/back/src/
masa/ # Path alias: @masa/*
masa.provider.ts # Facade service (this is what you inject)
masa.module.ts # NestJS module (imports ReferentielModule)
masa.dto.ts # DTOs returned by MasaProvider methods
referentiel/ # Path alias: @referentiel/*
lanceleau/ # Lanceleau schema (admin/identity data)
lanceleau.gateway.ts # Interface + Symbol (port)
lanceleau.repository.ts # TypeORM implementation (adapter)
roseau/ # Roseau schema (technical/infra data)
roseau.gateway.ts # Interface + Symbol (port)
roseau.repository.ts # TypeORM implementation (adapter)
referentiel.module.ts # Registers gateway providers
Important: @dossier/masa/ is a separate, unrelated concept (MASA webhook integration for file processing). Do not confuse it with @masa/ (the data facade).
import { MasaModule } from '@masa/masa.module';
@Module({
imports: [MasaModule],
providers: [MyNewService],
})
export class MyFeatureModule {}
import { Injectable } from '@nestjs/common';
import { MasaProvider } from '@masa/masa.provider';
@Injectable()
export class MyNewService {
constructor(private readonly masaProvider: MasaProvider) {}
async doSomething(steuCodes: string[]): Promise<void> {
const steus = await this.masaProvider.findSteuBatchBySandreCdas(steuCodes);
// ... business logic using steus
}
}
No @Inject() decorator is needed -- MasaProvider is a concrete class, not a Symbol-based gateway.
If MasaProvider doesn't expose the data you need yet:
LanceleauGateway or RoseauGateway interface)LanceleauRepository or RoseauRepository)apps/back/src/masa/masa.dto.ts for the return typeMasaProvider:// 1. Gateway interface (e.g., roseau.gateway.ts)
export interface RoseauGateway {
// ... existing methods
findMyNewData(param: string): Promise<MyNewDto[]>;
}
// 2. Repository implementation (e.g., roseau.repository.ts)
@Injectable()
export class RoseauRepository implements RoseauGateway {
async findMyNewData(param: string): Promise<MyNewDto[]> {
// TypeORM query
}
}
// 3. DTO (masa.dto.ts)
export interface MyNewDto {
code: string;
value: number;
}
// 4. MasaProvider pass-through (masa.provider.ts)
// Add a comment block following the existing pattern:
// ---------------------------------------------------------------------------
// CTL0XX — Description of the data purpose
// TODO: Remplacer par appel batch a l'API MASA quand disponible
// ---------------------------------------------------------------------------
async findMyNewData(param: string): Promise<MyNewDto[]> {
return this.roseauGateway.findMyNewData(param);
}
From controleV1DataFetcher.service.ts -- batch-loads all reference data needed for file validation:
import { MasaProvider } from '@masa/masa.provider';
@Injectable()
export class ControleV1DataFetcherService {
constructor(private readonly masaProvider: MasaProvider) {}
async load(fctAssainissement: FctAssainissement): Promise<ControleV1MasaData> {
const steuCdas = this.extractSteuCdas(fctAssainissement);
const exploitantRfas = this.extractExploitantRfas(fctAssainissement);
// Batch fetch in parallel
const [steus, itvs] = await Promise.all([
this.masaProvider.findSteuBatchBySandreCdas(steuCdas),
this.masaProvider.findItvBatchByRfas(exploitantRfas),
]);
// Second wave depends on first results
const expLinks = this.extractExpLinks(fctAssainissement, steus, itvs);
const [existingPmos, validSclAgaLinks, validExpSteuLinks] = await Promise.all([
this.masaProvider.checkPmoExistenceBatch(pmoQueries),
this.masaProvider.checkSclAgglomerationLinksBatch(sclLinks),
this.masaProvider.checkExpSteuLinksBatch(expLinks),
]);
return { steus, itvs, validExpSteuLinks, existingPmos, validSclAgaLinks };
}
}
In tests, mock MasaProvider directly -- it's a concrete class:
const mockMasaProvider = {
findSteuBatchBySandreCdas: jest.fn().mockResolvedValue([]),
findItvBatchByRfas: jest.fn().mockResolvedValue([]),
// ... mock only the methods your test needs
};
const module = await Test.createTestingModule({
providers: [MyService, { provide: MasaProvider, useValue: mockMasaProvider }],
}).compile();
MasaModule in your feature moduleMasaProvider (not gateways) in your service constructor@masa/masa.dto.tsTODO: Remplacer par appel ... API MASA commentMasaProvider -- only in your domain servicenpm run lint --workspace=apps/backRoseauGateway or LanceleauGateway in domain services -- breaks the migration strategy. When MASA API ships, you'd have to update every consumer instead of just MasaProvider.MasaProvider -- it must remain a pure data-access facade. Put logic in your domain service.@referentiel/ in domain code -- use DTOs from @masa/masa.dto.ts instead. Entities are implementation details that will disappear.MasaProvider.