@tmf/platform-core (1.2.0)
Installation
@tmf:registry=npm install @tmf/platform-core@1.2.0"@tmf/platform-core": "1.2.0"About this package
@tmf/platform-core
Base transversal do Modelo A da plataforma TMF: o pacote agnóstico de produto que todo módulo @tmf/* adota para falar com o host e com o Hub. Reúne o HttpClient (fetch nativo com Bearer + X-Client-Code), o cliente do contrato do Hub (createHubContractClient / useAppContract, com suporte a ETag), o ModuleProvider que recebe os ports injetados pelo host (i18n, toast, theme, http) e expõe contract, tenant, user, permissions e featureFlags por contexto, além das permissões (can / usePermission / Gate) e dos adapters opcionais (sonner, react-i18next, design-tokens). Não contém nenhuma lógica de domínio — é só o contrato de integração.
Nota: o pacote é publicado como
@tmf/platform-core; internamente os tipos e a documentação de conformidade ainda usam o nome histórico@tmf/module-kit(verCONFORMANCE.md).
Instalação
O pacote é privado e servido pelo registry npm do Forgejo (organização TMF):
npm config set @tmf:registry https://git.trademarketingforce.com/api/packages/TMF/npm/
npm i @tmf/platform-core
react e react-dom (>=18) são peerDependencies obrigatórias. sonner, react-i18next e @tmf/design-tokens são peerDeps opcionais — só necessárias se você importar os adapters correspondentes.
Uso básico
1. HttpClient — createHttpClient
Cliente HTTP sobre fetch nativo (sem axios). Injeta Authorization: Bearer via getToken e X-Client-Code quando clientCode é definido (multi-tenant):
import { createHttpClient } from '@tmf/platform-core';
const http = createHttpClient({
baseUrl: 'https://hub.trademarketingforce.com',
getToken: () => getMemoryToken() ?? '',
clientCode: 'ACME', // opcional — vira X-Client-Code
});
const tickets = await http.request<Ticket[]>('/api/tickets');
2. Contrato do Hub — createHubContractClient / useAppContract
Busca o AppContract em GET /api/platform/app-contract, normalizando o wire snake_case do Hub para o AppContract canônico (camelCase). Suporta cache condicional via ETag (If-None-Match → 304):
import { useAppContract } from '@tmf/platform-core';
const { contract, loading, error, refresh } = useAppContract({
baseUrl: 'https://hub.trademarketingforce.com',
getToken: () => getMemoryToken() ?? '',
});
O hook faz refresh automático por ttlSeconds (fallback de 60s). Para uso imperativo, use createHubContractClient({ baseUrl, getToken }).fetch(etag).
3. Provider — ModuleProvider
Monta o root do módulo com o contrato e os ports injetados pelo host. Aplica theme.cssVars no :root, carrega locale.messages no i18n e cria o http automaticamente se não for passado:
import { ModuleProvider } from '@tmf/platform-core';
import { createSonnerToastPort } from '@tmf/platform-core/adapters/sonner';
<ModuleProvider
contract={contract}
toast={createSonnerToastPort()}
getToken={() => getMemoryToken() ?? ''}
>
<MeuModulo />
</ModuleProvider>
Dentro da árvore, consuma via hooks: useModule(), useTenant(), useCurrentUser(), useModuleHttp(), useFeatureFlag(key), useServiceEndpoint(key). Guarde permissões com usePermission('perm') ou <Gate require="perm">…</Gate>.
Posição no Modelo A
@tmf/platform-core é a base de todos os módulos da plataforma. No Modelo A, a configuração (tenant, usuário, permissões, tema, locale, feature flags, endpoints de serviço) é servida pelo Hub via app-contract e entregue ao módulo por contexto — o módulo nunca lê localStorage direto nem importa sonner/react-i18next/design-tokens diretamente, apenas via ports/adapters do core.
Isso mantém o pacote agnóstico de produto: ele define o contrato de integração (ports, contrato Hub, permissões, provider) e nenhum comportamento de negócio. Cada módulo @tmf/* declara @tmf/platform-core como peerDependency e cumpre o checklist de CONFORMANCE.md.
Dependencies
Development dependencies
| ID | Version |
|---|---|
| @types/react | ^18.2.47 |
| @types/react-dom | ^18.2.18 |
| sonner | ^1.7.4 |
| typescript | ^5.3.3 |
Peer dependencies
| ID | Version |
|---|---|
| react | >=18.0.0 |
| react-dom | >=18.0.0 |