sgp-sdk 1.1.3 → 2.0.0-beta.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +87 -0
- package/COMPATIBILITY.md +151 -0
- package/MIGRATION.md +283 -0
- package/README.md +424 -225
- package/dist/address.d.ts +46 -0
- package/dist/annotation-selection.d.ts +32 -0
- package/dist/budget.d.ts +29 -0
- package/dist/classify.d.ts +15 -0
- package/dist/client.d.ts +662 -155
- package/dist/config.d.ts +115 -0
- package/dist/constants.d.ts +72 -0
- package/dist/effect.d.ts +22 -0
- package/dist/executor.d.ts +9 -0
- package/dist/exposure.d.ts +21 -0
- package/dist/guards.d.ts +2 -0
- package/dist/hooks.d.ts +16 -0
- package/dist/ids.d.ts +19 -0
- package/dist/index.d.ts +45 -47
- package/dist/index.js +2954 -1223
- package/dist/operation-sensitivity.d.ts +496 -0
- package/dist/operation.d.ts +139 -0
- package/dist/operations/catalogs-list-billing-profiles.d.ts +16 -0
- package/dist/operations/catalogs-list-nas.d.ts +25 -0
- package/dist/operations/catalogs-list-pops.d.ts +14 -0
- package/dist/operations/contracts-list-status-reasons.d.ts +15 -0
- package/dist/operations/contracts-list.d.ts +52 -0
- package/dist/operations/contracts-update-status.d.ts +41 -0
- package/dist/operations/contracts-update.d.ts +39 -0
- package/dist/operations/coverage-check.d.ts +42 -0
- package/dist/operations/crm-contracts-create-by-cpf-cnpj.d.ts +97 -0
- package/dist/operations/crm-contracts-create.d.ts +221 -0
- package/dist/operations/crm-contracts-list.d.ts +50 -0
- package/dist/operations/crm-customers-create.d.ts +155 -0
- package/dist/operations/crm-customers-update-status.d.ts +41 -0
- package/dist/operations/customers-list.d.ts +98 -0
- package/dist/{endpoints/ura/lookup-customer.d.ts → operations/customers-search.d.ts} +56 -46
- package/dist/operations/documents-add.d.ts +29 -0
- package/dist/operations/documents-list.d.ts +31 -0
- package/dist/operations/experimental-annotations-list.d.ts +67 -0
- package/dist/operations/invoices-list.d.ts +142 -0
- package/dist/operations/occurrences-create.d.ts +116 -0
- package/dist/operations/occurrences-list-methods.d.ts +14 -0
- package/dist/operations/occurrences-list-types.d.ts +20 -0
- package/dist/{endpoints/ura/list-plans.d.ts → operations/plans-list.d.ts} +33 -23
- package/dist/operations/pre-registrations-create.d.ts +253 -0
- package/dist/operations/pre-registrations-list-due-days.d.ts +15 -0
- package/dist/operations/pre-registrations-list-plans.d.ts +24 -0
- package/dist/operations/pre-registrations-list-sellers.d.ts +16 -0
- package/dist/operations/services-add-tv.d.ts +47 -0
- package/dist/operations/services-change-plan.d.ts +40 -0
- package/dist/operations/services-remove-tv.d.ts +29 -0
- package/dist/operations/work-orders-list-reasons.d.ts +20 -0
- package/dist/operations/work-orders-list.d.ts +81 -0
- package/dist/path.d.ts +13 -0
- package/dist/raw-request.d.ts +26 -0
- package/dist/request.d.ts +28 -0
- package/dist/result.d.ts +111 -43
- package/dist/retry.d.ts +34 -0
- package/dist/sensitivity.d.ts +89 -4
- package/dist/tolerant.d.ts +21 -0
- package/dist/validation.d.ts +3 -0
- package/package.json +6 -3
- package/dist/endpoint.d.ts +0 -66
- package/dist/endpoints/crm/address.d.ts +0 -20
- package/dist/endpoints/crm/create-contract.d.ts +0 -109
- package/dist/endpoints/crm/create-customer.d.ts +0 -65
- package/dist/endpoints/crm/update-customer-status.d.ts +0 -43
- package/dist/endpoints/os/list-occurrence-reasons.d.ts +0 -24
- package/dist/endpoints/os/list-occurrence-types.d.ts +0 -25
- package/dist/endpoints/precadastro/list-due-days.d.ts +0 -19
- package/dist/endpoints/precadastro/list-sellers.d.ts +0 -21
- package/dist/endpoints/suporte/add-customer-document.d.ts +0 -24
- package/dist/endpoints/suporte/list-customer-documents.d.ts +0 -25
- package/dist/endpoints/ura/check-coverage.d.ts +0 -46
- package/dist/endpoints/ura/list-clients.d.ts +0 -58
- package/dist/endpoints/ura/list-contracts.d.ts +0 -45
- package/dist/endpoints/ura/list-invoices.d.ts +0 -107
- package/dist/endpoints/ura/list-nas.d.ts +0 -29
- package/dist/endpoints/ura/list-occurrence-methods.d.ts +0 -19
- package/dist/endpoints/ura/list-payment-carriers.d.ts +0 -20
- package/dist/endpoints/ura/list-pops.d.ts +0 -19
- package/dist/endpoints/ura/list-service-orders.d.ts +0 -64
- package/dist/endpoints/ura/open-ticket.d.ts +0 -81
- package/dist/errors.d.ts +0 -59
- package/dist/schema/parse.d.ts +0 -19
- package/dist/schema/paths.d.ts +0 -38
- package/dist/transport.d.ts +0 -65
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Formato baseado em [Keep a Changelog](https://keepachangelog.com/pt-BR/1.1.0/); versionamento
|
|
4
|
+
[SemVer](https://semver.org/lang/pt-BR/). `experimental.*` é a exceção declarada: pode mudar de forma
|
|
5
|
+
incompatível em uma versão menor.
|
|
6
|
+
|
|
7
|
+
## 2.0.0-beta.1 (2026-11-06)
|
|
8
|
+
|
|
9
|
+
Redesenho completo como gateway de integração do SGP. Quebra de contrato sem aliases:
|
|
10
|
+
veja o [guia de migração](MIGRATION.md). Publicada na tag `next` do npm; `latest` continua na 1.2.0
|
|
11
|
+
até a 2.0.0 estável.
|
|
12
|
+
|
|
13
|
+
### Mudanças incompatíveis
|
|
14
|
+
|
|
15
|
+
- **Superfície nova, em inglês e agrupada por conceito do SGP**: `customers`, `crm.customers`,
|
|
16
|
+
`crm.contracts`, `preRegistrations`, `contracts`, `services`, `plans`, `occurrences`, `workOrders`,
|
|
17
|
+
`invoices`, `documents`, `coverage`, `catalogs`, `experimental.annotations` e `request()`. Os
|
|
18
|
+
namespaces `ura`, `os`, `precadastro`, `crm.*` antigos e `suporte` foram removidos; os campos dos
|
|
19
|
+
dados mantêm os nomes do SGP. Parâmetros posicionais (`clienteId`, `file`) viraram campos da
|
|
20
|
+
entrada.
|
|
21
|
+
- **Configuração**: `createSgpClient({ baseUrl, credentials: { kind: "token", token, app }, ... })`.
|
|
22
|
+
Configuração inválida **lança** `InvalidConfigurationError` na criação; `baseUrl` precisa ser uma
|
|
23
|
+
origem (sem caminho).
|
|
24
|
+
- **Modelo de resultado**: `{ ok, data, response, attempts, warnings? }` ou
|
|
25
|
+
`{ ok: false, error, response, attempts }`, no lugar de `success`/`error.status`/`error.detail`/
|
|
26
|
+
`error.endpoint`. `response` traz status, headers (credenciais redigidas) e corpo (`json`, `text`,
|
|
27
|
+
`empty`, `unavailable` ou `withheld`), ou `null` quando não houve resposta.
|
|
28
|
+
- **Códigos de erro**: `INVALID_INPUT`, `UNAUTHORIZED`, `FORBIDDEN`, `RATE_LIMITED`,
|
|
29
|
+
`ROUTE_NOT_ALLOWED` (restrição local do SDK: `request()` na rota de anotações), `NOT_FOUND`, `REJECTED`, `UPSTREAM`, `NETWORK`, `TIMEOUT`,
|
|
30
|
+
`ABORTED`, `INVALID_RESPONSE`. Saem `VALIDATION`, `METHOD_NOT_ALLOWED`, `SCHEMA_MISMATCH` e
|
|
31
|
+
`UNKNOWN`; o antigo `ROUTE_NOT_ALLOWED` virou `FORBIDDEN` com `reason: "TOKEN_ROUTE_NOT_ALLOWED"`.
|
|
32
|
+
- **Efeito de escritas**: `outcome` (`not_applied`/`unknown`) virou `error.effect` (`none`/`unknown`),
|
|
33
|
+
presente em toda escrita. `"none"` agora exige evidência (recusa local, cancelamento antes do envio,
|
|
34
|
+
erro de campo ou de negócio do SGP, ou recusa conhecida da operação); um 4xx de formato não
|
|
35
|
+
reconhecido é `"unknown"`.
|
|
36
|
+
- **Fidelidade**: chaves desconhecidas são preservadas em todos os níveis (o 1.x as descartava) e os
|
|
37
|
+
arrays que chegavam como `[{}]` agora chegam inteiros. Um item que não pode ser interpretado é
|
|
38
|
+
`INVALID_RESPONSE`. Campos secundários com tipo inesperado saem de `data` com `warnings`; o original
|
|
39
|
+
fica em `response.body`.
|
|
40
|
+
- **`coverage.check` não converte mais** `lat`, `lng` e `distancia` para número.
|
|
41
|
+
- **Entradas estritas**: chaves desconhecidas são recusadas localmente (`INVALID_INPUT`). Só os campos
|
|
42
|
+
que o fornecedor marca como obrigatórios são obrigatórios.
|
|
43
|
+
- **IDs com marca**: `CustomerId`, `PlanId` e `PreRegistrationPlanId` (tipos de compilação); os dois
|
|
44
|
+
catálogos de planos não se misturam.
|
|
45
|
+
- **Dados sensíveis**: `omitSensitive` e as tuplas `*SecretKeys`/`*PersonalKeys` foram substituídos por
|
|
46
|
+
`getSensitivity`, `pick` (allowlist) e `toSafeLog`.
|
|
47
|
+
- **Constantes renomeadas**: `formaCobrancaCodigo` para `BILLING_METHOD`, `modoAquisicao` para
|
|
48
|
+
`ACQUISITION_MODE`, `crmStatus` para `CRM_STATUS`.
|
|
49
|
+
- **Anotações**: `ura.listAnnotations` virou `experimental.annotations.list`. O corpo da resposta é
|
|
50
|
+
retido (`withheld`), cada anotação traz `raw`, identidade de outro cliente em qualquer profundidade
|
|
51
|
+
falha a chamada, e `request()` recusa a rota.
|
|
52
|
+
- Todos os exports `*Definition`, `*KeyFields` e `*ItemPath` foram removidos (a definição de uma
|
|
53
|
+
operação é interna).
|
|
54
|
+
|
|
55
|
+
### Adicionado
|
|
56
|
+
|
|
57
|
+
- Operações novas: `preRegistrations.create` (PF/PJ, endereço em campos soltos com os nomes do SGP) e `preRegistrations.listPlans`,
|
|
58
|
+
`contracts.update`, `contracts.updateStatus`, `contracts.listStatusReasons`, `services.changePlan`,
|
|
59
|
+
`services.addTv`, `services.removeTv`, `crm.contracts.createByCpfCnpj` e `crm.contracts.list`.
|
|
60
|
+
- `request()`: chamada bruta a uma rota que nenhum método cobre, com a mesma autenticação, prazo,
|
|
61
|
+
cancelamento e hooks (só caminhos sob `/api/`, sem redirecionamento, sem retry, `effect: "unknown"`
|
|
62
|
+
depois do envio).
|
|
63
|
+
- Por chamada: `abortSignal`, `timeoutMs` (um orçamento de tempo por chamada lógica) e `maxRetries`.
|
|
64
|
+
`TIMEOUT` (prazo do SDK) distinto de `ABORTED` (seu sinal).
|
|
65
|
+
- Retry opt-in para leituras (`maxRetries`, padrão 0), só em falhas transitórias, com backoff,
|
|
66
|
+
jitter e `Retry-After`. Escritas e `request()` nunca são repetidos. `attempts` em todo resultado.
|
|
67
|
+
- Hooks opcionais e síncronos (`onRequest`, `onResponse`, `onError`) só com metadados; um hook que
|
|
68
|
+
falha não altera o resultado (registro em `diagnostics`).
|
|
69
|
+
- `error.reason` por operação com evidência (`DOCUMENT_ALREADY_REGISTERED`, `STATUS_NOT_CHANGED`,
|
|
70
|
+
`CUSTOMER_NOT_IN_CRM`, `CONTRACT_NOT_ACTIVE`, `TOKEN_ROUTE_NOT_ALLOWED`) e `error.sgp` com os campos de
|
|
71
|
+
erro do SGP como vieram.
|
|
72
|
+
- Constantes `CONTRACT_STATUS` e `SERVICE_TYPE`; `ACQUISITION_MODE` compartilhada entre CRM e
|
|
73
|
+
pré-cadastro.
|
|
74
|
+
- Documentação em português: README, [MIGRATION.md](MIGRATION.md),
|
|
75
|
+
[COMPATIBILITY.md](COMPATIBILITY.md) e exemplos (`examples/` do repositório) compilados e executados na CI.
|
|
76
|
+
- CI no GitHub Actions e verificações do pacote construído (tipos de consumidor em NodeNext e Bundler,
|
|
77
|
+
smoke em Node e Bun, conteúdo do `npm pack`).
|
|
78
|
+
|
|
79
|
+
### Em aberto antes da 2.0.0 estável
|
|
80
|
+
|
|
81
|
+
- Testes unitários também no Node (hoje no Bun; o Node é coberto pelo smoke do pacote construído).
|
|
82
|
+
- Rotas e recusas ainda reconstruídas ou não observadas: veja [COMPATIBILITY.md](COMPATIBILITY.md).
|
|
83
|
+
|
|
84
|
+
## 1.x
|
|
85
|
+
|
|
86
|
+
Congelada. A última versão é a 1.2.0; as versões 1.0.0 a 1.2.0 estão nas tags `v1.0.0` a `v1.2.0` do
|
|
87
|
+
repositório.
|
package/COMPATIBILITY.md
ADDED
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
# Matriz de compatibilidade
|
|
2
|
+
|
|
3
|
+
O que foi **provado**, e como, para cada operação do sgp-sdk 2.0. Serve para saber até onde confiar
|
|
4
|
+
no contrato de uma operação antes de usá-la em produção.
|
|
5
|
+
|
|
6
|
+
- **Instância:** uma instância de produção de um provedor. Nenhuma outra foi usada.
|
|
7
|
+
- **Versão do SGP:** **desconhecida**. Nenhuma observação foi associada a uma versão do SGP, e
|
|
8
|
+
comportamento pode mudar entre versões.
|
|
9
|
+
- **Dados:** as escritas observadas usaram clientes, contratos e serviços de teste sintéticos criados
|
|
10
|
+
para a verificação. Esta matriz não traz hosts, credenciais nem identificadores reais, e omite ids.
|
|
11
|
+
- **Datas:** `AAAA-MM-DD` (UTC, a data do identificador da execução de verificação). Capturas feitas
|
|
12
|
+
para a série 1.x aparecem como "1.x" com a data em que a fixture entrou no repositório
|
|
13
|
+
(2026-10-30 a 2026-10-31); a data exata da captura não foi registrada (não verificado).
|
|
14
|
+
|
|
15
|
+
## Níveis de evidência
|
|
16
|
+
|
|
17
|
+
| Nível | Significa |
|
|
18
|
+
| --------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
19
|
+
| **Observado (bruta)** | Resposta real da instância, com status, headers e corpo registrados como foram recebidos. |
|
|
20
|
+
| **Observado (corpo)** | Resposta real da instância, mas só o corpo foi registrado (mascarado); os headers da fixture são reconstruídos. |
|
|
21
|
+
| **Documentado** | Descrito pelo fornecedor (coleção de requisições ou suporte), **nunca visto** numa resposta real. |
|
|
22
|
+
| **Reconstruído** | Corpo ou texto reconstruído de relatos (prosa de verificações), do contrato da série 1.x ou de testes, **sem captura**. O formato real pode diferir. |
|
|
23
|
+
|
|
24
|
+
Quando a resposta real difere do esperado, o SDK falha de forma segura: `INVALID_RESPONSE`, e numa
|
|
25
|
+
escrita `effect: "unknown"`. Um nível "Observado" prova **um** comportamento, uma vez ou poucas;
|
|
26
|
+
não é uma garantia de contrato do SGP. A prova de "nada foi aplicado" é uma releitura do estado, não
|
|
27
|
+
uma garantia.
|
|
28
|
+
|
|
29
|
+
As fixtures que alimentam os testes estão em `fixtures/` do repositório (fora do pacote npm), cada uma
|
|
30
|
+
com a fonte (`source`) e o nível de evidência (`evidence`) no próprio arquivo. A data da execução de
|
|
31
|
+
verificação aparece na fonte quando existe; as fixtures derivadas da série 1.x não têm data, e o
|
|
32
|
+
cenário é o caminho do arquivo (`<grupo>/<operação>/<caso>`).
|
|
33
|
+
|
|
34
|
+
## Matriz por operação
|
|
35
|
+
|
|
36
|
+
Cada linha é um cenário. As colunas "Data" e "Evidência" valem para aquele cenário.
|
|
37
|
+
|
|
38
|
+
### `customers`
|
|
39
|
+
|
|
40
|
+
| Operação | Cenário | Evidência | Data | Observação |
|
|
41
|
+
| ------------------ | ----------------------------------------------------------------- | ----------------- | ---------- | --------------------------------------------- |
|
|
42
|
+
| `customers.list` | Página de um cliente de teste, com contratos e serviços aninhados | Observado (corpo) | 2026-11-05 | Os aninhados chegam inteiros (nada de `[{}]`) |
|
|
43
|
+
| `customers.search` | Busca por contrato, um candidato | Observado (corpo) | 1.x | Corpo mascarado |
|
|
44
|
+
| `customers.search` | Sem resultado (`contratos: []`) | Reconstruído | n/d | Vem de um teste da 1.x |
|
|
45
|
+
|
|
46
|
+
### `crm`
|
|
47
|
+
|
|
48
|
+
| Operação | Cenário | Evidência | Data | Observação |
|
|
49
|
+
| ------------------------------- | ------------------------------------------------------------------- | ----------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------- |
|
|
50
|
+
| `crm.customers.create` | PF (`/F`): 200 com `cliente_id` e `message` | Observado (bruta) | 2026-11-05 | Com um CPF que já existia, o SGP criou **outro** cliente com o mesmo documento (ambos listados por `customers.list`) |
|
|
51
|
+
| `crm.customers.create` | PF: 400 de validação de campo (nome com dígitos) | Observado (bruta) | 2026-11-05 | Releitura: nada foi criado |
|
|
52
|
+
| `crm.customers.create` | PJ (`/J`) | Documentado | n/d | Nunca exercitado |
|
|
53
|
+
| `crm.customers.updateStatus` | Status 6 ("Contrato realizado no SGP"): 200 | Observado (bruta) | 2026-11-06 | Os demais códigos de `CRM_STATUS` nunca foram enviados |
|
|
54
|
+
| `crm.customers.updateStatus` | Cliente que já saiu do CRM: 404 `{error:"Cadastro não encontrado"}` | Reconstruído | 1.x | `NOT_FOUND`, `effect: "none"` |
|
|
55
|
+
| `crm.contracts.create` | Por id: 200 com `clientecontrato`, `message`, `cliente` | Observado (bruta) | 2026-11-06 | O contrato apareceu em `contracts.list` depois |
|
|
56
|
+
| `crm.contracts.create` | Por id: 400 por falta de `nas` | Observado (bruta) | 2026-11-06 | Nada foi criado |
|
|
57
|
+
| `crm.contracts.create` | Por id: 400 "Não encontrado cliente CRM" (`CUSTOMER_NOT_IN_CRM`) | Reconstruído | 2026-11-05 | Texto vindo da prosa do relato; a releitura mostrou nenhum contrato adicionado |
|
|
58
|
+
| `crm.contracts.create` | `modoaquisicao` 2 recusado | Observado (sem fixture) | 2026-10-31 | A documentação do fornecedor lista 1 e 2; o SDK aceita só 0 e 1 |
|
|
59
|
+
| `crm.contracts.create` | `login`, `senha`, `modoaquisicao` exigidos para serviço de Internet | Documentado | n/d | Só a falta de `nas` foi observada |
|
|
60
|
+
| `crm.contracts.createByCpfCnpj` | Sucesso (200) | Documentado | n/d | **Nenhum sucesso foi observado nesta rota**; assume-se o formato da rota por id |
|
|
61
|
+
| `crm.contracts.createByCpfCnpj` | 400 "Não encontrado cliente CRM" (`CUSTOMER_NOT_IN_CRM`) | Observado (bruta) | 2026-11-05 | Releitura: nada foi adicionado. Só CPF foi exercitado (CNPJ não) |
|
|
62
|
+
| `crm.contracts.list` | 200 com contratos | Observado (bruta) | 2026-11-06 | Valores pessoais mascarados |
|
|
63
|
+
| `crm.contracts.list` | 200 sem contratos | Observado (bruta) | 2026-11-05 | |
|
|
64
|
+
| `crm.contracts.list` | 400 para documento que não é cliente CRM | Observado (bruta) | 2026-11-05 | `REJECTED`, sem `reason` |
|
|
65
|
+
|
|
66
|
+
### `preRegistrations`
|
|
67
|
+
|
|
68
|
+
| Operação | Cenário | Evidência | Data | Observação |
|
|
69
|
+
| ------------------------------ | -------------------------------------------------- | ----------------- | ---------- | ---------------------------------------------------------------------------------------------------- |
|
|
70
|
+
| `preRegistrations.create` | Sucesso (`/F`): 200 `{ message }` | Documentado | 2026-11-05 | O texto do corpo é o exemplo do fornecedor; ao vivo só o status 200 e a chave `message` foram vistos |
|
|
71
|
+
| `preRegistrations.create` | CPF existente: 402 (`DOCUMENT_ALREADY_REGISTERED`) | Observado (bruta) | 2026-11-05 | Releitura: nenhum cliente nem contrato adicionado |
|
|
72
|
+
| `preRegistrations.create` | PJ (`/J`) | Documentado | n/d | Nunca exercitado; CNPJ não testado |
|
|
73
|
+
| `preRegistrations.listPlans` | Lista de planos do pré-cadastro | Observado (corpo) | 2026-11-05 | Requisição multipart, sem barra final |
|
|
74
|
+
| `preRegistrations.listDueDays` | Lista de vencimentos | Observado (corpo) | 1.x | |
|
|
75
|
+
| `preRegistrations.listSellers` | Lista de vendedores | Observado (corpo) | 1.x | |
|
|
76
|
+
|
|
77
|
+
### `contracts`
|
|
78
|
+
|
|
79
|
+
| Operação | Cenário | Evidência | Data | Observação |
|
|
80
|
+
| ----------------------------- | ------------------------------------------------------------------------------------------- | ------------------------------ | ---------- | ------------------------------------------------------------------------------------------------------------------------------------ |
|
|
81
|
+
| `contracts.list` | Filtro por contrato: array com um resumo | Observado (corpo) | 1.x | |
|
|
82
|
+
| `contracts.updateStatus` | Suspenso para Ativo: 200 com `resposta` | Observado (bruta) | 2026-11-05 | A releitura confirmou Ativo |
|
|
83
|
+
| `contracts.updateStatus` | Ativo para Suspenso: 200 com `resposta` | Observado (bruta) | 2026-11-05 | A releitura confirmou Suspenso |
|
|
84
|
+
| `contracts.updateStatus` | Inativo para Ativo: 200 | Observado, corpo não capturado | n/d | Confirmado por releitura |
|
|
85
|
+
| `contracts.updateStatus` | Ativo para Inativo: 400 `{error:"Status de Contrato não alterado."}` (`STATUS_NOT_CHANGED`) | Reconstruído | 2026-11-05 | Status e texto vêm do relato do suporte; a releitura mostrou o contrato ainda Ativo (o painel não oferece Inativo a partir de Ativo) |
|
|
86
|
+
| `contracts.updateStatus` | Status 6 ("Novo") | Documentado | n/d | Nunca observado; significado e transições desconhecidos |
|
|
87
|
+
| `contracts.updateStatus` | Status 3, 5 e 7 | Documentado | n/d | Vêm do painel do SGP; nunca enviados |
|
|
88
|
+
| `contracts.update` | `forma_cobranca`: 200 com `resposta.alterados` | Observado (bruta) | 2026-11-05 | A leitura seguinte mostrou a nova forma. Os demais campos documentados pelo fornecedor não são aceitos pelo SDK |
|
|
89
|
+
| `contracts.listStatusReasons` | Lista de motivos (`[{ id, motivo }]`) | Reconstruído | 2026-11-05 | Lista conhecida por prosa do suporte; formato do mapa de rotas validadas; sem captura |
|
|
90
|
+
|
|
91
|
+
### `services`
|
|
92
|
+
|
|
93
|
+
| Operação | Cenário | Evidência | Data | Observação |
|
|
94
|
+
| --------------------- | ---------------------------------------------------------------- | ----------------- | ---------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
|
95
|
+
| `services.changePlan` | 200 `{ msg }` (ida e volta de plano) | Observado (bruta) | 2026-11-05 | Observado duas vezes, corpo idêntico; só `servico_tipo` 1 enviado |
|
|
96
|
+
| `services.addTv` | 201 com `servico_id` | Observado (bruta) | 2026-11-05 | |
|
|
97
|
+
| `services.addTv` | 400 contrato não ativo (`CONTRACT_NOT_ACTIVE`) | Reconstruído | 2026-11-05 | Texto vindo da prosa do relato (o formato `errors` como array não está provado em captura bruta); a releitura mostrou nada adicionado |
|
|
98
|
+
| `services.removeTv` | 200 `{ msg, clientecontrato_id, servico_id }` (DELETE multipart) | Observado (bruta) | 2026-11-05 | Remoção do serviço criado na mesma execução |
|
|
99
|
+
|
|
100
|
+
### `plans`, `invoices`, `workOrders`, `occurrences`
|
|
101
|
+
|
|
102
|
+
| Operação | Cenário | Evidência | Data | Observação |
|
|
103
|
+
| ------------------------- | ------------------------------------------------------------------ | ----------------- | ---------- | ------------------------------------------------------------------------------------------------------------- |
|
|
104
|
+
| `plans.list` | Catálogo de planos | Observado (corpo) | 2026-11-05 | |
|
|
105
|
+
| `invoices.list` | Página vazia de um cliente sem títulos | Observado (corpo) | 2026-11-05 | |
|
|
106
|
+
| `invoices.list` | Página com títulos | Reconstruído | n/d | Nunca houve captura de uma página populada: chaves e tipos seguem a fixture da 1.x, os valores são inventados |
|
|
107
|
+
| `workOrders.list` | Filtro por contrato | Observado (corpo) | 2026-11-05 | |
|
|
108
|
+
| `workOrders.list` | Primeira página de várias (`limit` 1, `total` maior que `parcial`) | Observado (corpo) | 1.x | |
|
|
109
|
+
| `workOrders.listReasons` | Lista de motivos | Observado (corpo) | 1.x | `id` e `codigo` distintos |
|
|
110
|
+
| `occurrences.create` | Sucesso: `status` 1, `id`, `protocolo` | Observado (corpo) | 1.x | Corpo mascarado; a data da resposta não foi registrada |
|
|
111
|
+
| `occurrences.create` | Recusa: HTTP 200 com `status` 0 e `msg` | Reconstruído | n/d | Vem do contrato da 1.x; sem captura nem releitura, por isso `effect: "unknown"` |
|
|
112
|
+
| `occurrences.create` | Ligação ocorrência para OS pelo `protocolo` | Observado uma vez | n/d | **Não confirmada**: confira a OS antes de confiar nela |
|
|
113
|
+
| `occurrences.listTypes` | Lista de tipos | Observado (corpo) | 1.x | `classificacoes` e `setores` sempre vazios nas capturas |
|
|
114
|
+
| `occurrences.listMethods` | Lista de métodos | Observado (corpo) | 1.x | |
|
|
115
|
+
|
|
116
|
+
### `documents`, `coverage`, `catalogs`, `experimental`
|
|
117
|
+
|
|
118
|
+
| Operação | Cenário | Evidência | Data | Observação |
|
|
119
|
+
| ------------------------------- | ----------------------------------------- | ----------------- | ---- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
120
|
+
| `documents.add` | Sucesso: 2xx com corpo vazio | Reconstruído | n/d | Vem do contrato da 1.x e de seus testes; sem captura dos headers |
|
|
121
|
+
| `documents.list` | Lista de documentos | Observado (corpo) | 1.x | |
|
|
122
|
+
| `coverage.check` | Gateway SGPMaps; Geogrid; sem CTO no raio | Observado (corpo) | 1.x | Geogrid manda números como texto |
|
|
123
|
+
| `catalogs.listPops` | Lista de POPs | Observado (corpo) | 1.x | |
|
|
124
|
+
| `catalogs.listNas` | Lista de NAS | Observado (corpo) | 1.x | |
|
|
125
|
+
| `catalogs.listBillingProfiles` | Lista de portadores | Observado (corpo) | 1.x | |
|
|
126
|
+
| `experimental.annotations.list` | Resposta com anotações de vários clientes | Reconstruído | n/d | Corpo sintético no formato observado; os tipos dos campos foram contados ao vivo, sem persistir nenhuma anotação. Que o SGP ignora os filtros `cliente_id` e `contrato_id` foi observado ao vivo, mas sem captura positiva do cliente de teste |
|
|
127
|
+
|
|
128
|
+
### Comportamentos transversais
|
|
129
|
+
|
|
130
|
+
| Comportamento | Evidência | Observação |
|
|
131
|
+
| ---------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------ | --------------------------------------------------------------------------- |
|
|
132
|
+
| 403 "credenciais ... não foram fornecidas" (rota fora do token, barra final errada) e 403/401 "credenciais incorretas" | Observado (registro de decisão do projeto, 2026-11-05) | Corpo bruto não anexado ao repositório (não verificado) |
|
|
133
|
+
| Erros `errors` como array ("Ocorreu um erro: ...") são o invólucro genérico do SGP | Observado (registro de decisão do projeto) | Por isso ficam em `effect: "unknown"` salvo recusa conhecida da operação |
|
|
134
|
+
| `RATE_LIMITED` (429), limites de taxa do SGP | Nunca observado | O ajuste de retry é estimativa |
|
|
135
|
+
| 502 com corpo HTML como `UPSTREAM` | Coberto por teste | Se foi visto numa resposta real: não verificado |
|
|
136
|
+
| `request()` | Sem evidência própria | Depende da rota chamada: nenhum sucesso ou recusa de negócio é interpretado |
|
|
137
|
+
|
|
138
|
+
## Lacunas conhecidas
|
|
139
|
+
|
|
140
|
+
- Só PF e CPF foram exercitados em `preRegistrations.create` e `crm.customers.create`. PJ, CNPJ e os
|
|
141
|
+
tipos `E`/`EJ` não foram provados (`E`/`EJ` só via `request()`).
|
|
142
|
+
- O sucesso de `crm.contracts.createByCpfCnpj` nunca foi visto.
|
|
143
|
+
- Recusas que são apenas reconstruídas: `STATUS_NOT_CHANGED`, `CUSTOMER_NOT_IN_CRM` por id,
|
|
144
|
+
`CONTRACT_NOT_ACTIVE`, o 404 de `crm.customers.updateStatus` (só o corpo veio de uma captura da
|
|
145
|
+
1.x), a recusa `status: 0` de `occurrences.create` e o corpo vazio de `documents.add`. Se o SGP mandar outra forma, o efeito cai em `"unknown"`.
|
|
146
|
+
- Não se conhece rota de API para um segundo contrato de um cliente definitivo nem para extras de
|
|
147
|
+
serviço (roteador, multimídia, telefonia): hoje, só pelo painel do SGP.
|
|
148
|
+
- `experimental.annotations.list` depende do SGP corrigir o filtro no lado dele, e o isolamento local
|
|
149
|
+
é uma heurística por padrão de chave: dados de outro cliente sob chaves que não são de identidade
|
|
150
|
+
não seriam detectados.
|
|
151
|
+
- Limites de taxa do SGP e a ligação ocorrência para OS por `protocolo` não foram confirmados.
|
package/MIGRATION.md
ADDED
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
# Migração do 1.x para o 2.0
|
|
2
|
+
|
|
3
|
+
A 2.0 é uma quebra de contrato deliberada: novos nomes, novo modelo de resultado, novos códigos de
|
|
4
|
+
erro e mais fidelidade aos dados do SGP. **Não há aliases**: nenhum método ou export do 1.x
|
|
5
|
+
permanece. A série 1.x (última: 1.2.0) está congelada e não recebe mais mudanças; quem não puder
|
|
6
|
+
migrar já deve fixar essa versão.
|
|
7
|
+
|
|
8
|
+
O guia está na ordem em que a migração costuma acontecer: [cliente](#1-criação-do-cliente),
|
|
9
|
+
[métodos](#2-mapa-de-métodos), [resultado](#3-modelo-de-resultado),
|
|
10
|
+
[erros](#4-códigos-de-erro), [escritas](#5-escritas-outcome-vira-effect),
|
|
11
|
+
[comportamento](#6-mudanças-de-comportamento), [exports](#7-exports-removidos-e-renomeados).
|
|
12
|
+
|
|
13
|
+
## 1. Criação do cliente
|
|
14
|
+
|
|
15
|
+
```ts
|
|
16
|
+
// 1.x
|
|
17
|
+
const sgp = createSgpClient({ baseUrl, token, app, timeoutMs, fetch });
|
|
18
|
+
|
|
19
|
+
// 2.0
|
|
20
|
+
const sgp = createSgpClient({
|
|
21
|
+
baseUrl, // somente a origem: sem caminho, query ou credenciais
|
|
22
|
+
credentials: { kind: "token", token, app },
|
|
23
|
+
timeoutMs, // agora é o padrão por chamada (20 000 ms se omitido)
|
|
24
|
+
maxRetries, // novo, opcional (padrão 0)
|
|
25
|
+
hooks, // novo, opcional
|
|
26
|
+
fetch,
|
|
27
|
+
});
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
- `token` e `app` soltos deixam de existir: vão em `credentials`.
|
|
31
|
+
- `createSgpClient` **lança** `InvalidConfigurationError` para configuração inválida (URL que não é uma
|
|
32
|
+
origem `http(s)`, token ou app vazios, `timeoutMs` ou `maxRetries` fora do domínio, hooks que não
|
|
33
|
+
são funções). No 1.x a configuração não era validada. Um `baseUrl` com prefixo de caminho (que o
|
|
34
|
+
1.x concatenava às rotas) agora é recusado.
|
|
35
|
+
- As chamadas aceitam um último argumento `options` com `abortSignal`, `timeoutMs` e `maxRetries`.
|
|
36
|
+
|
|
37
|
+
## 2. Mapa de métodos
|
|
38
|
+
|
|
39
|
+
Parâmetros posicionais (`clienteId`, `file`) passaram a campos do objeto de entrada, com os nomes do
|
|
40
|
+
SGP.
|
|
41
|
+
|
|
42
|
+
| 1.x | 2.0 |
|
|
43
|
+
| ------------------------------------------------------- | ----------------------------------------------------------------------- |
|
|
44
|
+
| `ura.listClients(params?)` | `customers.list(input?)` |
|
|
45
|
+
| `ura.lookupCustomer(params)` | `customers.search(input)` |
|
|
46
|
+
| `ura.listContracts(params?)` | `contracts.list(input?)` |
|
|
47
|
+
| `ura.listServiceOrders(params?)` | `workOrders.list(input?)` |
|
|
48
|
+
| `ura.listInvoices(params?)` | `invoices.list(input?)` |
|
|
49
|
+
| `ura.listPlans()` | `plans.list()` |
|
|
50
|
+
| `ura.listPops()` | `catalogs.listPops()` |
|
|
51
|
+
| `ura.listNas()` | `catalogs.listNas()` |
|
|
52
|
+
| `ura.listPaymentCarriers()` | `catalogs.listBillingProfiles()` |
|
|
53
|
+
| `ura.checkCoverage(params)` | `coverage.check(input)` |
|
|
54
|
+
| `ura.listOccurrenceMethods()` | `occurrences.listMethods()` |
|
|
55
|
+
| `ura.openTicket(params)` | `occurrences.create(input)` |
|
|
56
|
+
| `ura.listAnnotations(params)` (experimental) | `experimental.annotations.list(input)` (continua experimental) |
|
|
57
|
+
| `os.listOccurrenceTypes()` | `occurrences.listTypes()` |
|
|
58
|
+
| `os.listOccurrenceReasons()` | `workOrders.listReasons()` |
|
|
59
|
+
| `precadastro.listDueDays()` | `preRegistrations.listDueDays()` |
|
|
60
|
+
| `precadastro.listSellers()` | `preRegistrations.listSellers()` |
|
|
61
|
+
| `crm.createIndividualCustomer(params)` | `crm.customers.create({ personType: "F", ... })` |
|
|
62
|
+
| `crm.createCompanyCustomer(params)` | `crm.customers.create({ personType: "J", ... })` |
|
|
63
|
+
| `crm.createContract(clienteId, params)` | `crm.contracts.create({ cliente_id: clienteId, ... })` |
|
|
64
|
+
| `crm.updateCustomerStatus(clienteId, params)` | `crm.customers.updateStatus({ cliente_id: clienteId, status_id, ... })` |
|
|
65
|
+
| `suporte.addCustomerDocument(clienteId, file, params?)` | `documents.add({ cliente_id: clienteId, file, descricao? })` |
|
|
66
|
+
| `suporte.listCustomerDocuments(clienteId)` | `documents.list({ cliente_id: clienteId })` |
|
|
67
|
+
|
|
68
|
+
Nada do 1.x foi removido sem equivalente: os 23 métodos acima têm destino.
|
|
69
|
+
|
|
70
|
+
Operações que **não existiam** no 1.x: `preRegistrations.create`, `preRegistrations.listPlans`,
|
|
71
|
+
`contracts.update`, `contracts.updateStatus`, `contracts.listStatusReasons`, `services.changePlan`,
|
|
72
|
+
`services.addTv`, `services.removeTv`, `crm.contracts.createByCpfCnpj`, `crm.contracts.list` e
|
|
73
|
+
`request()`. Veja o [README](README.md#referência-de-operações).
|
|
74
|
+
|
|
75
|
+
Mudanças de forma na entrada, além da posição dos argumentos:
|
|
76
|
+
|
|
77
|
+
- Os endereços mantêm os nomes do SGP: `crm.customers.create` segue com `endereco` e
|
|
78
|
+
`crm.contracts.create` com `endereco_instalacao` e `endereco_cobranca`. `preRegistrations.create`
|
|
79
|
+
(nova no 2.0) recebe o endereço em campos soltos no topo da entrada (`logradouro`, `numero`,
|
|
80
|
+
`bairro`, `cidade`, `cep`, `uf`, ...), sem agrupamento.
|
|
81
|
+
- O arquivo de `documents.add` mantém o formato `{ data, filename, contentType? }` (o tipo se chama
|
|
82
|
+
agora `DocumentFile`).
|
|
83
|
+
- Toda entrada é verificada localmente e **chaves desconhecidas são recusadas** (`INVALID_INPUT`).
|
|
84
|
+
Para um campo que a operação ainda não cobre, use `request()`.
|
|
85
|
+
|
|
86
|
+
## 3. Modelo de resultado
|
|
87
|
+
|
|
88
|
+
```ts
|
|
89
|
+
// 1.x
|
|
90
|
+
if (result.success) {
|
|
91
|
+
result.data;
|
|
92
|
+
result.warnings;
|
|
93
|
+
} else {
|
|
94
|
+
result.error.status;
|
|
95
|
+
result.error.code;
|
|
96
|
+
result.error.detail;
|
|
97
|
+
result.error.endpoint;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// 2.0
|
|
101
|
+
if (result.ok) {
|
|
102
|
+
result.data;
|
|
103
|
+
result.warnings;
|
|
104
|
+
result.response;
|
|
105
|
+
result.attempts;
|
|
106
|
+
} else {
|
|
107
|
+
result.error.code;
|
|
108
|
+
result.error.sgp;
|
|
109
|
+
result.error.operation;
|
|
110
|
+
result.response;
|
|
111
|
+
result.attempts;
|
|
112
|
+
}
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
| 1.x | 2.0 |
|
|
116
|
+
| -------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
117
|
+
| `success: boolean` | `ok: boolean` |
|
|
118
|
+
| `error.status` (0 sem resposta) | `response?.status`; `response` é `null` quando não houve resposta HTTP (inclui recusa local) |
|
|
119
|
+
| `error.detail` (texto único) | `error.sgp`: `detail`, `msg`, `error` e `errors` **com os valores como vieram**; compor um texto é com você |
|
|
120
|
+
| `error.endpoint` (caminho) | `error.operation` (nome da operação, ex.: `customers.list`); o caminho não faz mais parte do erro |
|
|
121
|
+
| `error.message` | igual: escrita pelo SDK, em inglês |
|
|
122
|
+
| (não havia) | `error.reason` (por operação), `error.issues` (caminhos de `INVALID_RESPONSE`), `attempts`, `diagnostics` |
|
|
123
|
+
| (corpo bruto nunca disponível) | `response.status`, `response.headers` (credenciais redigidas) e `response.body` em todo resultado com resposta |
|
|
124
|
+
| `SchemaWarning { path, expected, received }` | acrescenta `dropped`: o campo que de fato ficou fora de `data` |
|
|
125
|
+
|
|
126
|
+
`SgpResult` e `SgpWriteResult` viraram um tipo só, `SgpResult<T>`. Veja o
|
|
127
|
+
[modelo de resultado](README.md#o-modelo-de-resultado).
|
|
128
|
+
|
|
129
|
+
## 4. Códigos de erro
|
|
130
|
+
|
|
131
|
+
| 1.x | 2.0 |
|
|
132
|
+
| ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
133
|
+
| `UNAUTHORIZED` | `UNAUTHORIZED` (HTTP 401 sempre; 403 com credenciais incorretas) |
|
|
134
|
+
| `ROUTE_NOT_ALLOWED` | `FORBIDDEN` com `reason: "TOKEN_ROUTE_NOT_ALLOWED"` (403 "credenciais não foram fornecidas"). Um 401 com esse texto é `UNAUTHORIZED`. `ROUTE_NOT_ALLOWED` ainda existe como código, para a restrição local do SDK: hoje só `request()` na rota de anotações o devolve |
|
|
135
|
+
| `NOT_FOUND` | `NOT_FOUND` |
|
|
136
|
+
| `METHOD_NOT_ALLOWED` | `REJECTED` (o 405 não tem código próprio) |
|
|
137
|
+
| `VALIDATION` (status 0, recusa local) | `INVALID_INPUT` (`attempts: 0`, `response: null`) |
|
|
138
|
+
| `VALIDATION` (4xx do SGP) | `REJECTED`, ou `RATE_LIMITED` no 429 |
|
|
139
|
+
| `VALIDATION` (2xx de escrita que não confirma) | `INVALID_RESPONSE` |
|
|
140
|
+
| `SCHEMA_MISMATCH` | `INVALID_RESPONSE`, com `error.issues` apontando os caminhos (sem valores) |
|
|
141
|
+
| `UPSTREAM` | `UPSTREAM` (5xx) |
|
|
142
|
+
| `TIMEOUT` | `TIMEOUT` para o prazo do SDK; **`ABORTED`** para o seu `abortSignal` (que o 1.x não tinha) |
|
|
143
|
+
| `NETWORK` | `NETWORK` |
|
|
144
|
+
| `UNKNOWN` | deixa de existir: 401/403 de outro tipo viram `UNAUTHORIZED`/`FORBIDDEN`; 3xx e demais status fora do contrato viram `INVALID_RESPONSE` |
|
|
145
|
+
|
|
146
|
+
Novo: `INVALID_INPUT`, `FORBIDDEN`, `RATE_LIMITED` (nunca observado), `REJECTED`, `ABORTED`,
|
|
147
|
+
`INVALID_RESPONSE`. A classificação agora se faz pelo **status HTTP**, e o corpo só refina o 403
|
|
148
|
+
(o 1.x lia o texto também para decidir 401).
|
|
149
|
+
|
|
150
|
+
## 5. Escritas: `outcome` vira `effect`
|
|
151
|
+
|
|
152
|
+
| 1.x | 2.0 |
|
|
153
|
+
| ---------------------------------------------------- | ------------------------------------ |
|
|
154
|
+
| `error.outcome === "not_applied"` | `error.effect === "none"` |
|
|
155
|
+
| `error.outcome === "unknown"` | `error.effect === "unknown"` |
|
|
156
|
+
| `SgpWriteResult<T>`, `SgpWriteError`, `WriteOutcome` | `SgpResult<T>`, `SgpError`, `Effect` |
|
|
157
|
+
|
|
158
|
+
A regra mudou, e é mais conservadora:
|
|
159
|
+
|
|
160
|
+
- 1.x: qualquer 4xx era `not_applied`, exceto o invólucro genérico do SGP (`errors` como array).
|
|
161
|
+
- 2.0: `"none"` exige evidência: recusa local, cancelamento antes do envio, 4xx com formato de erro de
|
|
162
|
+
campo ou de negócio (`errors` como objeto, `error` ou `detail` como texto) ou uma recusa que a
|
|
163
|
+
operação declara como conhecida. Um 4xx com corpo ilegível ou de formato não reconhecido é
|
|
164
|
+
`"unknown"`.
|
|
165
|
+
- O 1.x só dava `outcome` em `crm.*`, `ura.openTicket` e `suporte.addCustomerDocument`. No 2.0
|
|
166
|
+
**toda escrita** tem `effect`, incluindo as novas, e `request()` (sempre `"unknown"` depois do envio).
|
|
167
|
+
- A recusa de `ura.openTicket` com HTTP 200 e `status: 0` era `VALIDATION`/`unknown`; agora é
|
|
168
|
+
`REJECTED` com `effect: "unknown"`.
|
|
169
|
+
|
|
170
|
+
Os `reason`s conhecidos e o que fazer diante de `"unknown"` estão no README.
|
|
171
|
+
|
|
172
|
+
## 6. Mudanças de comportamento
|
|
173
|
+
|
|
174
|
+
**Fidelidade.** O 1.x descartava chaves desconhecidas em todos os níveis e declarava como `[{}]` os
|
|
175
|
+
arrays sem amostra, o que fazia `ura.listClients` devolver `contratos: [{}]` como se estivesse certo.
|
|
176
|
+
A 2.0 preserva toda chave que recebe, em todos os níveis, e tipa o que conhece:
|
|
177
|
+
|
|
178
|
+
- Acabaram os arrays-placeholder do 1.x (`clientes[].contratos`/`titulos`, `contratos[].telefones_cargos`,
|
|
179
|
+
`outros`, `anotacoes`, `ordens_servicos[].tecnicos_auxiliares`/`classificacoes`, `planos[].combo`,
|
|
180
|
+
`classificacoes`/`setores` de tipos e motivos, `acordados`/`cobrados` de títulos): chegam como o SGP
|
|
181
|
+
mandou.
|
|
182
|
+
- Ausente, `null` e `""` são preservados. Um item que o SDK não consegue interpretar é
|
|
183
|
+
`INVALID_RESPONSE`, nunca um objeto vazio.
|
|
184
|
+
- Campos estruturais (ids e o que a navegação exige) têm validação estrita (`INVALID_RESPONSE`); campos
|
|
185
|
+
secundários com tipo inesperado saem de `data` com um `warning`, e o original fica em `response.body`.
|
|
186
|
+
- `coverage.check` **não converte** mais nada: `lat`, `lng` e `distancia` que o Geogrid manda como
|
|
187
|
+
texto continuam texto. Confira o tipo antes de calcular.
|
|
188
|
+
- As listas que o SGP pagina (`customers.list`, `workOrders.list`, `invoices.list`) devolvem uma
|
|
189
|
+
página com a `paginacao` do SGP; `total` nunca é calculado. As sem paginação mantêm o formato do SGP.
|
|
190
|
+
|
|
191
|
+
**IDs com marca.** `CustomerId`, `PlanId` e `PreRegistrationPlanId` são tipos de compilação: um número
|
|
192
|
+
solto não é aceito onde um id é esperado, nem um id de plano onde cabe um de cliente. Marque um
|
|
193
|
+
número em que você confia com `as CustomerId`. Os dois catálogos de planos (`plans.list` e
|
|
194
|
+
`preRegistrations.listPlans`) têm espaços de ids diferentes e nunca se misturam.
|
|
195
|
+
|
|
196
|
+
**Obrigatoriedade.** Só os campos que o fornecedor marca como obrigatórios são obrigatórios; regras do
|
|
197
|
+
painel do SGP não são validadas localmente. A decisão de aceitar ou não vem do SGP.
|
|
198
|
+
|
|
199
|
+
**Tempo, cancelamento e retry.** Um orçamento de tempo por chamada (tentativas, esperas e leitura do
|
|
200
|
+
corpo), `timeoutMs` e `abortSignal` por chamada. O 1.x não tinha retry e continua sem retry por padrão:
|
|
201
|
+
`maxRetries` (padrão 0) é opt-in e vale só para leituras, em falhas transitórias. **Escritas nunca são
|
|
202
|
+
repetidas** (como no 1.x), e `request()` também não.
|
|
203
|
+
|
|
204
|
+
**Hooks.** `onRequest`, `onResponse` e `onError`, síncronos, só com metadados. Um hook que falha
|
|
205
|
+
nunca muda o resultado.
|
|
206
|
+
|
|
207
|
+
**Redirecionamentos.** Continuam sem ser seguidos; a diferença é que um 3xx agora é `INVALID_RESPONSE`
|
|
208
|
+
(no 1.x era `UNKNOWN`).
|
|
209
|
+
|
|
210
|
+
**Anotações (`experimental.annotations.list`).** Chaves desconhecidas deixam de ser descartadas, e cada
|
|
211
|
+
anotação traz `raw`. O corpo da resposta é retido (`{ kind: "withheld" }`) em qualquer status, e uma
|
|
212
|
+
anotação com identidade indecidível ou de outro cliente, em qualquer profundidade, falha a chamada
|
|
213
|
+
inteira com `INVALID_RESPONSE`. `request()` recusa essa rota.
|
|
214
|
+
|
|
215
|
+
**Cobrança, status e aquisição.** Os códigos agora são constantes em inglês (veja abaixo). O valor 2 de
|
|
216
|
+
`modoaquisicao` continua não aceito (recusado ao vivo).
|
|
217
|
+
|
|
218
|
+
**Dados sensíveis.** `omitSensitive` e as tuplas por endpoint (`clientPersonalKeys` etc.) foram
|
|
219
|
+
substituídos por três ferramentas (denylist deu lugar a allowlist):
|
|
220
|
+
|
|
221
|
+
| 1.x | 2.0 |
|
|
222
|
+
| --------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
|
|
223
|
+
| tuplas `*SecretKeys` / `*PersonalKeys` por endpoint | `getSensitivity("customers.list")`: chaves secretas e pessoais da entrada e da resposta, por caminho |
|
|
224
|
+
| `omitSensitive(item, chaves)` (remove as listadas) | `pick(origem, allowlist)` (só sai o que for nomeado) |
|
|
225
|
+
| (não havia) | `toSafeLog(result)`: versão de um resultado própria para log |
|
|
226
|
+
|
|
227
|
+
Os corpos em `response.body` **não** são redigidos (os headers são): podem repetir credenciais ou
|
|
228
|
+
dados pessoais. Nunca registre o resultado cru.
|
|
229
|
+
|
|
230
|
+
## 7. Exports removidos e renomeados
|
|
231
|
+
|
|
232
|
+
**Removidos sem substituto:** as `*Definition`, `*KeyFields`, `*ItemPath`, `*SecretKeys`,
|
|
233
|
+
`*PersonalKeys`, `listAnnotationsSchema`, `omitSensitive`. A definição de uma operação é interna.
|
|
234
|
+
|
|
235
|
+
**Constantes e tipos:**
|
|
236
|
+
|
|
237
|
+
| 1.x | 2.0 |
|
|
238
|
+
| ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
239
|
+
| `formaCobrancaCodigo` (`boleto`, `debitoAutomatico`, `carne`, `cobrancaRecorrente`, `pix`) | `BILLING_METHOD` (`boleto`, `automaticDebit`, `booklet`, `recurringCharge`, `pix`) |
|
|
240
|
+
| `modoAquisicao` (`proprio`, `comodato`) | `ACQUISITION_MODE` (`owned`, `loan`) |
|
|
241
|
+
| `crmStatus` (`emAnalise` ... `analiseViabilidadeTecnica`) | `CRM_STATUS` (`underAnalysis`, `approved`, `rejected`, `awaitingContact`, `tryingContact`, `contractMadeInSgp`, `technicalInfeasibility`, `contractInProspecting`, `rejectedCreditBureau`, `technicalFeasibilityAnalysis`) |
|
|
242
|
+
| (não havia) | `CONTRACT_STATUS`, `SERVICE_TYPE` |
|
|
243
|
+
| `FormaCobrancaCodigo`, `ModoAquisicao`, `CrmStatusId` | `BillingMethod`, `AcquisitionMode`, `CrmStatus` |
|
|
244
|
+
| `SgpClientConfig` | `ClientOptions` |
|
|
245
|
+
| `SgpFile` | `DocumentFile` |
|
|
246
|
+
| `SgpWriteResult`, `SgpWriteError`, `WriteOutcome` | `SgpResult`, `SgpError`, `Effect` |
|
|
247
|
+
| `UraClient`, `OsClient`, `PrecadastroClient`, `SuporteClient` | clientes por grupo (`CustomersClient`, `ContractsClient`, ...) dentro de `SgpClient` |
|
|
248
|
+
|
|
249
|
+
**Tipos de entrada e resposta** (`*Params`/`*Response` viraram `*Input`/`*Data`):
|
|
250
|
+
|
|
251
|
+
| 1.x | 2.0 |
|
|
252
|
+
| ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
|
|
253
|
+
| `ListClientsParams` / `ListClientsResponse` | `CustomersListInput` / `CustomersListData` |
|
|
254
|
+
| `LookupCustomerParams` / `LookupCustomerResponse` | `CustomersSearchInput` / `CustomersSearchData` |
|
|
255
|
+
| `ListContractsParams` / `ListContractsResponse` | `ContractsListInput` / `ContractsListData` |
|
|
256
|
+
| `ListServiceOrdersParams` / `ListServiceOrdersResponse` | `WorkOrdersListInput` / `WorkOrdersListData` |
|
|
257
|
+
| `ListInvoicesParams` / `ListInvoicesResponse` | `InvoicesListInput` / `InvoicesListData` |
|
|
258
|
+
| `ListPlansResponse` | `PlansListData` (e `PlanId`) |
|
|
259
|
+
| `ListPopsResponse`, `ListNasResponse`, `ListPaymentCarriersResponse` | `CatalogsListPopsData`, `CatalogsListNasData`, `CatalogsListBillingProfilesData` |
|
|
260
|
+
| `CheckCoverageParams` / `CheckCoverageResponse` | `CoverageCheckInput` / `CoverageCheckData` |
|
|
261
|
+
| `ListOccurrenceMethodsResponse`, `ListOccurrenceTypesResponse`, `ListOccurrenceReasonsResponse` | `OccurrencesListMethodsData`, `OccurrencesListTypesData`, `WorkOrdersListReasonsData` |
|
|
262
|
+
| `OpenTicketParams` / `OpenTicketResponse` | `OccurrenceCreateInput` / `OccurrenceCreateData` |
|
|
263
|
+
| `ListDueDaysResponse`, `ListSellersResponse` | `PreRegistrationsListDueDaysData`, `PreRegistrationsListSellersData` |
|
|
264
|
+
| `CreateIndividualCustomerParams`, `CreateCompanyCustomerParams`, `CreateCustomerResponse` | `CrmCustomerCreateIndividualInput`, `CrmCustomerCreateCompanyInput` (união: `CrmCustomerCreateInput`), `CrmCustomerCreateData` |
|
|
265
|
+
| `CreateContractParams` / `CreateContractResponse` | `CrmContractCreateInput` / `CrmContractCreateData` |
|
|
266
|
+
| `UpdateCustomerStatusParams` / `UpdateCustomerStatusResponse` | `CrmCustomerUpdateStatusInput` / `CrmCustomerUpdateStatusData` |
|
|
267
|
+
| `AddCustomerDocumentParams` (a resposta era `data: null`) | `DocumentAddInput` (inclui `cliente_id` e `file`); a resposta continua `null` |
|
|
268
|
+
| `ListCustomerDocumentsResponse` | `DocumentsListData` |
|
|
269
|
+
| `ListAnnotationsParams` / `ListAnnotationsResponse` | `ExperimentalAnnotationsListInput` / `ExperimentalAnnotationsListData` |
|
|
270
|
+
|
|
271
|
+
`SgpAddress` continua exportado. `SgpResult`, `SgpError`, `SgpErrorCode` e `SchemaWarning` mantêm o
|
|
272
|
+
nome, com o formato novo descrito acima.
|
|
273
|
+
|
|
274
|
+
## Roteiro sugerido
|
|
275
|
+
|
|
276
|
+
1. Troque a criação do cliente (`credentials`) e trate `InvalidConfigurationError` na inicialização.
|
|
277
|
+
2. Renomeie os métodos pela tabela e passe os argumentos posicionais para o objeto de entrada.
|
|
278
|
+
3. Troque `success` por `ok`, `error.status` por `response?.status`, `error.detail` por `error.sgp` e os
|
|
279
|
+
`switch` de `error.code` pelos códigos novos.
|
|
280
|
+
4. Nas escritas, troque `outcome` por `effect` e releia o estado antes de reenviar após `"unknown"`.
|
|
281
|
+
5. Substitua `omitSensitive` e as tuplas por `pick`/`toSafeLog`/`getSensitivity`.
|
|
282
|
+
6. Rode a verificação de tipos: ids com marca e chaves desconhecidas aparecem como erros de
|
|
283
|
+
compilação ou como `INVALID_INPUT`.
|