sgp-sdk 1.2.0 → 2.0.0-beta.2

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.
Files changed (100) hide show
  1. package/CHANGELOG.md +234 -0
  2. package/COMPATIBILITY.md +231 -0
  3. package/MIGRATION.md +344 -0
  4. package/README.md +464 -265
  5. package/dist/address.d.ts +46 -0
  6. package/dist/annotation-selection.d.ts +32 -0
  7. package/dist/budget.d.ts +29 -0
  8. package/dist/classify.d.ts +15 -0
  9. package/dist/client.d.ts +938 -165
  10. package/dist/config.d.ts +115 -0
  11. package/dist/constants.d.ts +85 -0
  12. package/dist/document.d.ts +11 -0
  13. package/dist/effect.d.ts +22 -0
  14. package/dist/executor.d.ts +9 -0
  15. package/dist/exposure.d.ts +21 -0
  16. package/dist/guards.d.ts +2 -0
  17. package/dist/hooks.d.ts +16 -0
  18. package/dist/ids.d.ts +19 -0
  19. package/dist/index.d.ts +55 -49
  20. package/dist/index.js +3750 -1293
  21. package/dist/normalize.d.ts +9 -0
  22. package/dist/operation-sensitivity.d.ts +729 -0
  23. package/dist/operation.d.ts +145 -0
  24. package/dist/operations/catalogs-list-billing-profiles.d.ts +16 -0
  25. package/dist/operations/catalogs-list-nas.d.ts +25 -0
  26. package/dist/operations/catalogs-list-pops.d.ts +14 -0
  27. package/dist/operations/contracts-check-connection.d.ts +56 -0
  28. package/dist/operations/contracts-list-services.d.ts +103 -0
  29. package/dist/operations/contracts-list-status-reasons.d.ts +15 -0
  30. package/dist/operations/contracts-list.d.ts +52 -0
  31. package/dist/operations/contracts-update-status.d.ts +41 -0
  32. package/dist/operations/contracts-update.d.ts +39 -0
  33. package/dist/operations/coverage-check-address.d.ts +46 -0
  34. package/dist/operations/coverage-check.d.ts +43 -0
  35. package/dist/operations/coverage-list-gateways.d.ts +16 -0
  36. package/dist/operations/crm-contracts-create-by-cpf-cnpj.d.ts +97 -0
  37. package/dist/operations/crm-contracts-create.d.ts +221 -0
  38. package/dist/operations/crm-contracts-list.d.ts +50 -0
  39. package/dist/operations/crm-customers-create.d.ts +165 -0
  40. package/dist/operations/crm-customers-update-status.d.ts +41 -0
  41. package/dist/operations/customers-list.d.ts +104 -0
  42. package/dist/{endpoints/ura/lookup-customer.d.ts → operations/customers-search.d.ts} +56 -46
  43. package/dist/operations/documents-add.d.ts +29 -0
  44. package/dist/operations/documents-list.d.ts +31 -0
  45. package/dist/operations/experimental-annotations-list.d.ts +67 -0
  46. package/dist/operations/invoices-list.d.ts +148 -0
  47. package/dist/operations/maintenance-list.d.ts +35 -0
  48. package/dist/operations/occurrences-create.d.ts +125 -0
  49. package/dist/operations/occurrences-list-methods.d.ts +14 -0
  50. package/dist/operations/occurrences-list-types.d.ts +20 -0
  51. package/dist/operations/occurrences-list.d.ts +127 -0
  52. package/dist/{endpoints/ura/list-plans.d.ts → operations/plans-list.d.ts} +33 -23
  53. package/dist/operations/pre-registrations-create.d.ts +276 -0
  54. package/dist/operations/pre-registrations-list-due-days.d.ts +15 -0
  55. package/dist/operations/pre-registrations-list-plans.d.ts +24 -0
  56. package/dist/operations/pre-registrations-list-sellers.d.ts +16 -0
  57. package/dist/operations/services-add-generic.d.ts +52 -0
  58. package/dist/operations/services-add-tv.d.ts +47 -0
  59. package/dist/operations/services-change-plan.d.ts +40 -0
  60. package/dist/operations/services-remove-generic.d.ts +28 -0
  61. package/dist/operations/services-remove-tv.d.ts +29 -0
  62. package/dist/operations/work-orders-get.d.ts +99 -0
  63. package/dist/operations/work-orders-list-comments.d.ts +34 -0
  64. package/dist/operations/work-orders-list-reasons.d.ts +20 -0
  65. package/dist/operations/work-orders-list.d.ts +81 -0
  66. package/dist/path.d.ts +13 -0
  67. package/dist/raw-request.d.ts +26 -0
  68. package/dist/request.d.ts +28 -0
  69. package/dist/result.d.ts +113 -41
  70. package/dist/retry.d.ts +34 -0
  71. package/dist/sensitivity.d.ts +89 -4
  72. package/dist/tolerant.d.ts +21 -0
  73. package/dist/validation.d.ts +3 -0
  74. package/package.json +6 -3
  75. package/dist/endpoint.d.ts +0 -66
  76. package/dist/endpoints/crm/address.d.ts +0 -20
  77. package/dist/endpoints/crm/create-contract.d.ts +0 -109
  78. package/dist/endpoints/crm/create-customer.d.ts +0 -65
  79. package/dist/endpoints/crm/update-customer-status.d.ts +0 -43
  80. package/dist/endpoints/os/list-occurrence-reasons.d.ts +0 -24
  81. package/dist/endpoints/os/list-occurrence-types.d.ts +0 -25
  82. package/dist/endpoints/precadastro/list-due-days.d.ts +0 -19
  83. package/dist/endpoints/precadastro/list-sellers.d.ts +0 -21
  84. package/dist/endpoints/suporte/add-customer-document.d.ts +0 -24
  85. package/dist/endpoints/suporte/list-customer-documents.d.ts +0 -25
  86. package/dist/endpoints/ura/check-coverage.d.ts +0 -46
  87. package/dist/endpoints/ura/list-annotations.d.ts +0 -32
  88. package/dist/endpoints/ura/list-clients.d.ts +0 -58
  89. package/dist/endpoints/ura/list-contracts.d.ts +0 -45
  90. package/dist/endpoints/ura/list-invoices.d.ts +0 -107
  91. package/dist/endpoints/ura/list-nas.d.ts +0 -29
  92. package/dist/endpoints/ura/list-occurrence-methods.d.ts +0 -19
  93. package/dist/endpoints/ura/list-payment-carriers.d.ts +0 -20
  94. package/dist/endpoints/ura/list-pops.d.ts +0 -19
  95. package/dist/endpoints/ura/list-service-orders.d.ts +0 -64
  96. package/dist/endpoints/ura/open-ticket.d.ts +0 -81
  97. package/dist/errors.d.ts +0 -59
  98. package/dist/schema/parse.d.ts +0 -19
  99. package/dist/schema/paths.d.ts +0 -38
  100. package/dist/transport.d.ts +0 -65
package/MIGRATION.md ADDED
@@ -0,0 +1,344 @@
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
+ [beta.1 para beta.2](#8-da-200-beta1-para-a-200-beta2).
13
+
14
+ ## 1. Criação do cliente
15
+
16
+ ```ts
17
+ // 1.x
18
+ const sgp = createSgpClient({ baseUrl, token, app, timeoutMs, fetch });
19
+
20
+ // 2.0
21
+ const sgp = createSgpClient({
22
+ baseUrl, // somente a origem: sem caminho, query ou credenciais
23
+ credentials: { kind: "token", token, app },
24
+ timeoutMs, // agora é o padrão por chamada (20 000 ms se omitido)
25
+ maxRetries, // novo, opcional (padrão 0)
26
+ hooks, // novo, opcional
27
+ fetch,
28
+ });
29
+ ```
30
+
31
+ - `token` e `app` soltos deixam de existir: vão em `credentials`.
32
+ - `createSgpClient` **lança** `InvalidConfigurationError` para configuração inválida (URL que não é uma
33
+ origem `http(s)`, token ou app vazios, `timeoutMs` ou `maxRetries` fora do domínio, hooks que não
34
+ são funções). No 1.x a configuração não era validada. Um `baseUrl` com prefixo de caminho (que o
35
+ 1.x concatenava às rotas) agora é recusado.
36
+ - As chamadas aceitam um último argumento `options` com `abortSignal`, `timeoutMs` e `maxRetries`.
37
+
38
+ ## 2. Mapa de métodos
39
+
40
+ Parâmetros posicionais (`clienteId`, `file`) passaram a campos do objeto de entrada, com os nomes do
41
+ SGP.
42
+
43
+ | 1.x | 2.0 |
44
+ | ------------------------------------------------------- | ----------------------------------------------------------------------- |
45
+ | `ura.listClients(params?)` | `customers.list(input?)` |
46
+ | `ura.lookupCustomer(params)` | `customers.search(input)` |
47
+ | `ura.listContracts(params?)` | `contracts.list(input?)` |
48
+ | `ura.listServiceOrders(params?)` | `workOrders.list(input?)` |
49
+ | `ura.listInvoices(params?)` | `invoices.list(input?)` |
50
+ | `ura.listPlans()` | `plans.list()` |
51
+ | `ura.listPops()` | `catalogs.listPops()` |
52
+ | `ura.listNas()` | `catalogs.listNas()` |
53
+ | `ura.listPaymentCarriers()` | `catalogs.listBillingProfiles()` |
54
+ | `ura.checkCoverage(params)` | `coverage.check(input)` |
55
+ | `ura.listOccurrenceMethods()` | `occurrences.listMethods()` |
56
+ | `ura.openTicket(params)` | `occurrences.create(input)` |
57
+ | `ura.listAnnotations(params)` (experimental) | `experimental.annotations.list(input)` (continua experimental) |
58
+ | `os.listOccurrenceTypes()` | `occurrences.listTypes()` |
59
+ | `os.listOccurrenceReasons()` | `workOrders.listReasons()` |
60
+ | `precadastro.listDueDays()` | `preRegistrations.listDueDays()` |
61
+ | `precadastro.listSellers()` | `preRegistrations.listSellers()` |
62
+ | `crm.createIndividualCustomer(params)` | `crm.customers.create({ personType: "F", ... })` |
63
+ | `crm.createCompanyCustomer(params)` | `crm.customers.create({ personType: "J", ... })` |
64
+ | `crm.createContract(clienteId, params)` | `crm.contracts.create({ cliente_id: clienteId, ... })` |
65
+ | `crm.updateCustomerStatus(clienteId, params)` | `crm.customers.updateStatus({ cliente_id: clienteId, status_id, ... })` |
66
+ | `suporte.addCustomerDocument(clienteId, file, params?)` | `documents.add({ cliente_id: clienteId, file, descricao? })` |
67
+ | `suporte.listCustomerDocuments(clienteId)` | `documents.list({ cliente_id: clienteId })` |
68
+
69
+ Nada do 1.x foi removido sem equivalente: os 23 métodos acima têm destino.
70
+
71
+ Operações que **não existiam** no 1.x: `preRegistrations.create`, `preRegistrations.listPlans`,
72
+ `contracts.update`, `contracts.updateStatus`, `contracts.listStatusReasons`, `services.changePlan`,
73
+ `services.addTv`, `services.removeTv`, `services.addGeneric`, `services.removeGeneric`, `crm.contracts.createByCpfCnpj`, `crm.contracts.list` e
74
+ `request()`. Veja o [README](README.md#referência-de-operações).
75
+
76
+ Mudanças de forma na entrada, além da posição dos argumentos:
77
+
78
+ - Os endereços mantêm os nomes do SGP: `crm.customers.create` segue com `endereco` e
79
+ `crm.contracts.create` com `endereco_instalacao` e `endereco_cobranca`. `preRegistrations.create`
80
+ (nova no 2.0) recebe o endereço em campos soltos no topo da entrada (`logradouro`, `numero`,
81
+ `bairro`, `cidade`, `cep`, `uf`, ...), sem agrupamento.
82
+ - O arquivo de `documents.add` mantém o formato `{ data, filename, contentType? }` (o tipo se chama
83
+ agora `DocumentFile`).
84
+ - Toda entrada é verificada localmente e **chaves desconhecidas são recusadas** (`INVALID_INPUT`).
85
+ Para um campo que a operação ainda não cobre, use `request()`.
86
+
87
+ ## 3. Modelo de resultado
88
+
89
+ ```ts
90
+ // 1.x
91
+ if (result.success) {
92
+ result.data;
93
+ result.warnings;
94
+ } else {
95
+ result.error.status;
96
+ result.error.code;
97
+ result.error.detail;
98
+ result.error.endpoint;
99
+ }
100
+
101
+ // 2.0
102
+ if (result.ok) {
103
+ result.data;
104
+ result.warnings;
105
+ result.response;
106
+ result.attempts;
107
+ } else {
108
+ result.error.code;
109
+ result.error.sgp;
110
+ result.error.operation;
111
+ result.response;
112
+ result.attempts;
113
+ }
114
+ ```
115
+
116
+ | 1.x | 2.0 |
117
+ | -------------------------------------------- | -------------------------------------------------------------------------------------------------------------- |
118
+ | `success: boolean` | `ok: boolean` |
119
+ | `error.status` (0 sem resposta) | `response?.status`; `response` é `null` quando não houve resposta HTTP (inclui recusa local) |
120
+ | `error.detail` (texto único) | `error.sgp`: `detail`, `msg`, `error` e `errors` **com os valores como vieram**; compor um texto é com você |
121
+ | `error.endpoint` (caminho) | `error.operation` (nome da operação, ex.: `customers.list`); o caminho não faz mais parte do erro |
122
+ | `error.message` | igual: escrita pelo SDK, em inglês |
123
+ | (não havia) | `error.reason` (por operação), `error.issues` (caminhos de `INVALID_RESPONSE`), `attempts`, `diagnostics` |
124
+ | (corpo bruto nunca disponível) | `response.status`, `response.headers` (credenciais redigidas) e `response.body` em todo resultado com resposta |
125
+ | `SchemaWarning { path, expected, received }` | acrescenta `dropped`: o campo que de fato ficou fora de `data` |
126
+
127
+ `SgpResult` e `SgpWriteResult` viraram um tipo só, `SgpResult<T>`. Veja o
128
+ [modelo de resultado](README.md#o-modelo-de-resultado).
129
+
130
+ ## 4. Códigos de erro
131
+
132
+ | 1.x | 2.0 |
133
+ | ---------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
134
+ | `UNAUTHORIZED` | `UNAUTHORIZED` (HTTP 401 sempre; 403 com credenciais incorretas) |
135
+ | `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 |
136
+ | `NOT_FOUND` | `NOT_FOUND` |
137
+ | `METHOD_NOT_ALLOWED` | `REJECTED` (o 405 não tem código próprio) |
138
+ | `VALIDATION` (status 0, recusa local) | `INVALID_INPUT` (`attempts: 0`, `response: null`) |
139
+ | `VALIDATION` (4xx do SGP) | `REJECTED`, ou `RATE_LIMITED` no 429 |
140
+ | `VALIDATION` (2xx de escrita que não confirma) | `INVALID_RESPONSE` |
141
+ | `SCHEMA_MISMATCH` | `INVALID_RESPONSE`, com `error.issues` apontando os caminhos (sem valores) |
142
+ | `UPSTREAM` | `UPSTREAM` (5xx) |
143
+ | `TIMEOUT` | `TIMEOUT` para o prazo do SDK; **`ABORTED`** para o seu `abortSignal` (que o 1.x não tinha) |
144
+ | `NETWORK` | `NETWORK` |
145
+ | `UNKNOWN` | deixa de existir: 401/403 de outro tipo viram `UNAUTHORIZED`/`FORBIDDEN`; 3xx e demais status fora do contrato viram `INVALID_RESPONSE` |
146
+
147
+ Novo: `INVALID_INPUT`, `FORBIDDEN`, `RATE_LIMITED` (nunca observado), `REJECTED`, `ABORTED`,
148
+ `INVALID_RESPONSE`. A classificação agora se faz pelo **status HTTP**, e o corpo só refina o 403
149
+ (o 1.x lia o texto também para decidir 401).
150
+
151
+ ## 5. Escritas: `outcome` vira `effect`
152
+
153
+ | 1.x | 2.0 |
154
+ | ---------------------------------------------------- | ------------------------------------ |
155
+ | `error.outcome === "not_applied"` | `error.effect === "none"` |
156
+ | `error.outcome === "unknown"` | `error.effect === "unknown"` |
157
+ | `SgpWriteResult<T>`, `SgpWriteError`, `WriteOutcome` | `SgpResult<T>`, `SgpError`, `Effect` |
158
+
159
+ A regra mudou, e é mais conservadora:
160
+
161
+ - 1.x: qualquer 4xx era `not_applied`, exceto o invólucro genérico do SGP (`errors` como array).
162
+ - 2.0: `"none"` exige evidência: recusa local, cancelamento antes do envio, 4xx com formato de erro de
163
+ campo ou de negócio (`errors` como objeto, `error` ou `detail` como texto) ou uma recusa que a
164
+ operação declara como conhecida. Um 4xx com corpo ilegível ou de formato não reconhecido é
165
+ `"unknown"`.
166
+ - O 1.x só dava `outcome` em `crm.*`, `ura.openTicket` e `suporte.addCustomerDocument`. No 2.0
167
+ **toda escrita** tem `effect`, incluindo as novas, e `request()` (sempre `"unknown"` depois do envio).
168
+ - A recusa de `ura.openTicket` com HTTP 200 e `status: 0` era `VALIDATION`/`unknown`; agora é
169
+ `REJECTED` com `effect: "unknown"`; só a do agendamento com formato inválido (`msg` "Data e hora de
170
+ agendamento inválida ...") traz `reason: "INVALID_SCHEDULE"` e `effect: "none"`.
171
+
172
+ Os `reason`s conhecidos e o que fazer diante de `"unknown"` estão no README.
173
+
174
+ ## 6. Mudanças de comportamento
175
+
176
+ **Fidelidade.** O 1.x descartava chaves desconhecidas em todos os níveis e declarava como `[{}]` os
177
+ arrays sem amostra, o que fazia `ura.listClients` devolver `contratos: [{}]` como se estivesse certo.
178
+ A 2.0 preserva toda chave que recebe, em todos os níveis, e tipa o que conhece:
179
+
180
+ - Acabaram os arrays-placeholder do 1.x (`clientes[].contratos`/`titulos`, `contratos[].telefones_cargos`,
181
+ `outros`, `anotacoes`, `ordens_servicos[].tecnicos_auxiliares`/`classificacoes`, `planos[].combo`,
182
+ `classificacoes`/`setores` de tipos e motivos, `acordados`/`cobrados` de títulos): chegam como o SGP
183
+ mandou.
184
+ - Ausente, `null` e `""` são preservados. Um item que o SDK não consegue interpretar é
185
+ `INVALID_RESPONSE`, nunca um objeto vazio.
186
+ - Campos estruturais (ids e o que a navegação exige) têm validação estrita (`INVALID_RESPONSE`); campos
187
+ secundários com tipo inesperado saem de `data` com um `warning`, e o original fica em `response.body`.
188
+ - Tipos de alguns campos são normalizados por campo (ver [a seção 8](#8-da-200-beta1-para-a-200-beta2)):
189
+ onde o SGP varia o tipo, `data` traz um só.
190
+ - As listas que o SGP pagina (`customers.list`, `workOrders.list`, `invoices.list`) devolvem uma
191
+ página com a `paginacao` do SGP; `total` nunca é calculado. As sem paginação mantêm o formato do SGP.
192
+
193
+ **IDs com marca.** `CustomerId`, `PlanId` e `PreRegistrationPlanId` são tipos de compilação: um número
194
+ solto não é aceito onde um id é esperado, nem um id de plano onde cabe um de cliente. Marque um
195
+ número em que você confia com `as CustomerId`. Os dois catálogos de planos (`plans.list` e
196
+ `preRegistrations.listPlans`) têm espaços de ids diferentes e nunca se misturam.
197
+
198
+ **Obrigatoriedade.** Só os campos que o fornecedor marca como obrigatórios são obrigatórios; regras do
199
+ painel do SGP não são validadas localmente. A decisão de aceitar ou não vem do SGP.
200
+
201
+ **Tempo, cancelamento e retry.** Um orçamento de tempo por chamada (tentativas, esperas e leitura do
202
+ corpo), `timeoutMs` e `abortSignal` por chamada. O 1.x não tinha retry e continua sem retry por padrão:
203
+ `maxRetries` (padrão 0) é opt-in e vale só para leituras, em falhas transitórias. **Escritas nunca são
204
+ repetidas** (como no 1.x), e `request()` também não.
205
+
206
+ **Hooks.** `onRequest`, `onResponse` e `onError`, síncronos, só com metadados. Um hook que falha
207
+ nunca muda o resultado.
208
+
209
+ **Redirecionamentos.** Continuam sem ser seguidos; a diferença é que um 3xx agora é `INVALID_RESPONSE`
210
+ (no 1.x era `UNKNOWN`).
211
+
212
+ **Anotações (`experimental.annotations.list`).** Chaves desconhecidas deixam de ser descartadas, e cada
213
+ anotação traz `raw`. O corpo da resposta é retido (`{ kind: "withheld" }`) em qualquer status, e uma
214
+ anotação com identidade indecidível ou de outro cliente, em qualquer profundidade, falha a chamada
215
+ inteira com `INVALID_RESPONSE`. `request()` recusa essa rota.
216
+
217
+ **Cobrança, status e aquisição.** Os códigos agora são constantes em inglês (veja abaixo). O valor 2 de
218
+ `modoaquisicao` continua não aceito (recusado ao vivo).
219
+
220
+ **Dados sensíveis.** `omitSensitive` e as tuplas por endpoint (`clientPersonalKeys` etc.) foram
221
+ substituídos por três ferramentas (denylist deu lugar a allowlist):
222
+
223
+ | 1.x | 2.0 |
224
+ | --------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
225
+ | tuplas `*SecretKeys` / `*PersonalKeys` por endpoint | `getSensitivity("customers.list")`: chaves secretas e pessoais da entrada e da resposta, por caminho |
226
+ | `omitSensitive(item, chaves)` (remove as listadas) | `pick(origem, allowlist)` (só sai o que for nomeado) |
227
+ | (não havia) | `toSafeLog(result)`: versão de um resultado própria para log |
228
+
229
+ Os corpos em `response.body` **não** são redigidos (os headers são): podem repetir credenciais ou
230
+ dados pessoais. Nunca registre o resultado cru.
231
+
232
+ ## 7. Exports removidos e renomeados
233
+
234
+ **Removidos sem substituto:** as `*Definition`, `*KeyFields`, `*ItemPath`, `*SecretKeys`,
235
+ `*PersonalKeys`, `listAnnotationsSchema`, `omitSensitive`. A definição de uma operação é interna.
236
+
237
+ **Constantes e tipos:**
238
+
239
+ | 1.x | 2.0 |
240
+ | ------------------------------------------------------------------------------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
241
+ | `formaCobrancaCodigo` (`boleto`, `debitoAutomatico`, `carne`, `cobrancaRecorrente`, `pix`) | `BILLING_METHOD` (`boleto`, `automaticDebit`, `booklet`, `recurringCharge`, `pix`) |
242
+ | `modoAquisicao` (`proprio`, `comodato`) | `ACQUISITION_MODE` (`owned`, `loan`) |
243
+ | `crmStatus` (`emAnalise` ... `analiseViabilidadeTecnica`) | `CRM_STATUS` (`underAnalysis`, `approved`, `rejected`, `awaitingContact`, `tryingContact`, `contractMadeInSgp`, `technicalInfeasibility`, `contractInProspecting`, `rejectedCreditBureau`, `technicalFeasibilityAnalysis`) |
244
+ | (não havia) | `CONTRACT_STATUS`, `SERVICE_TYPE` |
245
+ | `FormaCobrancaCodigo`, `ModoAquisicao`, `CrmStatusId` | `BillingMethod`, `AcquisitionMode`, `CrmStatus` |
246
+ | `SgpClientConfig` | `ClientOptions` |
247
+ | `SgpFile` | `DocumentFile` |
248
+ | `SgpWriteResult`, `SgpWriteError`, `WriteOutcome` | `SgpResult`, `SgpError`, `Effect` |
249
+ | `UraClient`, `OsClient`, `PrecadastroClient`, `SuporteClient` | clientes por grupo (`CustomersClient`, `ContractsClient`, ...) dentro de `SgpClient` |
250
+
251
+ **Tipos de entrada e resposta** (`*Params`/`*Response` viraram `*Input`/`*Data`):
252
+
253
+ | 1.x | 2.0 |
254
+ | ----------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
255
+ | `ListClientsParams` / `ListClientsResponse` | `CustomersListInput` / `CustomersListData` |
256
+ | `LookupCustomerParams` / `LookupCustomerResponse` | `CustomersSearchInput` / `CustomersSearchData` |
257
+ | `ListContractsParams` / `ListContractsResponse` | `ContractsListInput` / `ContractsListData` |
258
+ | `ListServiceOrdersParams` / `ListServiceOrdersResponse` | `WorkOrdersListInput` / `WorkOrdersListData` |
259
+ | `ListInvoicesParams` / `ListInvoicesResponse` | `InvoicesListInput` / `InvoicesListData` |
260
+ | `ListPlansResponse` | `PlansListData` (e `PlanId`) |
261
+ | `ListPopsResponse`, `ListNasResponse`, `ListPaymentCarriersResponse` | `CatalogsListPopsData`, `CatalogsListNasData`, `CatalogsListBillingProfilesData` |
262
+ | `CheckCoverageParams` / `CheckCoverageResponse` | `CoverageCheckInput` / `CoverageCheckData` |
263
+ | `ListOccurrenceMethodsResponse`, `ListOccurrenceTypesResponse`, `ListOccurrenceReasonsResponse` | `OccurrencesListMethodsData`, `OccurrencesListTypesData`, `WorkOrdersListReasonsData` |
264
+ | `OpenTicketParams` / `OpenTicketResponse` | `OccurrenceCreateInput` / `OccurrenceCreateData` |
265
+ | `ListDueDaysResponse`, `ListSellersResponse` | `PreRegistrationsListDueDaysData`, `PreRegistrationsListSellersData` |
266
+ | `CreateIndividualCustomerParams`, `CreateCompanyCustomerParams`, `CreateCustomerResponse` | `CrmCustomerCreateIndividualInput`, `CrmCustomerCreateCompanyInput` (união: `CrmCustomerCreateInput`), `CrmCustomerCreateData` |
267
+ | `CreateContractParams` / `CreateContractResponse` | `CrmContractCreateInput` / `CrmContractCreateData` |
268
+ | `UpdateCustomerStatusParams` / `UpdateCustomerStatusResponse` | `CrmCustomerUpdateStatusInput` / `CrmCustomerUpdateStatusData` |
269
+ | `AddCustomerDocumentParams` (a resposta era `data: null`) | `DocumentAddInput` (inclui `cliente_id` e `file`); a resposta continua `null` |
270
+ | `ListCustomerDocumentsResponse` | `DocumentsListData` |
271
+ | `ListAnnotationsParams` / `ListAnnotationsResponse` | `ExperimentalAnnotationsListInput` / `ExperimentalAnnotationsListData` |
272
+
273
+ `SgpAddress` continua exportado. `SgpResult`, `SgpError`, `SgpErrorCode` e `SchemaWarning` mantêm o
274
+ nome, com o formato novo descrito acima.
275
+
276
+ ## 8. Da 2.0.0-beta.1 para a 2.0.0-beta.2
277
+
278
+ A beta.2 **normaliza o tipo de campos que o SGP manda com tipo variável ou em texto**. É uma em geral uma
279
+ mudança de tipo (quebra de compilação onde você usava o tipo antigo; `invoices.list` é a exceção, abaixo); os nomes não mudam, campos desconhecidos
280
+ ficam como vieram, e o corpo original segue em `response.body`. Regras: número (JSON ou texto com `.`
281
+ decimal e sem separador de milhar) vira `number`; `""` e `null` viram `null` (nunca `0`); texto
282
+ formatado (`"1.234,56"`) nunca é adivinhado: o campo sai de `data` com um `warning`.
283
+
284
+ | Operação | Campo | beta.1 | beta.2 |
285
+ | ------------------------------------- | ------------------------------------------- | ---------------------------------------- | ------------------------------- |
286
+ | `coverage.check` | `lat`, `lng`, `distancia`, `id` de cada CTO | `number \| string` (Geogrid manda texto) | `number \| null` |
287
+ | `services.addTv`, `services.removeTv` | `clientecontrato_id` | `string` | `number \| null` |
288
+ | `workOrders.get` | `servico_id`, `contrato_status_id` | `string` | `number \| null` |
289
+ | `workOrders.get` | `os_setor_id` | `number \| string` | `number \| null` |
290
+ | `workOrders.get` | `contrato_status` | `" Suspenso"` (espaço à esquerda) | `"Suspenso"` (aparado) |
291
+ | `preRegistrations.listPlans` | `gateway.gateway_id`, `gateway.id` | `string \| number` (`""` sem gateway) | `number \| null` |
292
+ | `preRegistrations.create` | `precadastro_id`, `new_contrato_id` | `unknown` (chave não tipada) | `number \| null` (opcional) |
293
+ | `preRegistrations.create` | `new_cliente_id` | `unknown` (chave não tipada) | `CustomerId \| null` (opcional) |
294
+
295
+ Em `preRegistrations.create`, os três ids do sucesso passam a ter tipo, mas **continuam opcionais**: o
296
+ SDK não os inventa, e quando o SGP os omite você segue relendo o cliente por `customers.list({ cpfcnpj })`.
297
+ Os registros mais antigos listam só `message` e o decoder da 1.x descartava chaves desconhecidas, então não
298
+ se sabe se o SGP já enviava os ids antes.
299
+
300
+ **`invoices.list` é mudança de comportamento, não de tipo.** `titulos[].valor`, `valorDesconto`,
301
+ `valorCorrigido`, `valorPago` e `valorPagoParcial` já eram `number | null` na beta.1. O que muda: um `""`
302
+ em `valor` (o SGP manda texto vazio quando não há valor) saía de `data` com um `warning`; agora chega como
303
+ `null`, nunca como `0`. Texto formatado (`"1.234,56"`) continua saindo de `data` com `warning`.
304
+
305
+ **`cpfcnpj` das escritas que gravam o documento.** `preRegistrations.create` e `crm.customers.create`
306
+ passam a enviar o documento na máscara canônica e a recusar localmente o que não for CPF (`personType:
307
+ "F"`) ou CNPJ (`"J"`):
308
+
309
+ | Entrada (`F`) | beta.1 enviava | beta.2 envia ou faz |
310
+ | ------------------------- | --------------- | ------------------------------------------ |
311
+ | `"00000000191"` | `"00000000191"` | `"000.000.001-91"` |
312
+ | `"000.000.001-91"` | igual | igual |
313
+ | `"000 000 001/91"` | igual | `"000.000.001-91"` |
314
+ | `"00000000000191"` (CNPJ) | igual | `INVALID_INPUT` em `cpfcnpj`, nada enviado |
315
+ | `""` ou `"abc"` | igual | `INVALID_INPUT` em `cpfcnpj`, nada enviado |
316
+
317
+ | Entrada (`J`) | beta.1 enviava | beta.2 envia ou faz |
318
+ | ----------------------------------------- | -------------- | ------------------------------------------ |
319
+ | `"00000000000191"` | igual | `"00.000.000/0001-91"` |
320
+ | `"12abc34501de35"` | igual | `"12.ABC.345/01DE-35"` (maiúsculas) |
321
+ | `"12.ABC.345/01DE-35"` | igual | igual |
322
+ | `"12ABC34501DEAB"` (letras nas 2 últimas) | igual | `INVALID_INPUT` em `cpfcnpj`, nada enviado |
323
+ | `"00000000191"` (CPF) | igual | `INVALID_INPUT` em `cpfcnpj`, nada enviado |
324
+
325
+ A recusa traz `error.code === "INVALID_INPUT"`, `attempts: 0`, `effect: "none"` e
326
+ `error.issues` igual a `["cpfcnpj: expected a CPF for personType F: ..."]` (ou `CNPJ`/`J`), sem o valor.
327
+ Só o formato é conferido: os dígitos verificadores não. Trate `INVALID_INPUT` com `error.issues` no
328
+ lugar de formatar o documento por conta própria. Os filtros `cpfcnpj` de leitura não mudam. Quem
329
+ guardou clientes com o documento só em dígitos continua com esses cadastros no SGP: o SDK não os
330
+ corrige.
331
+
332
+ Se você comparava `contrato_status` com o texto com espaço, ou fazia `Number(servico_id)`, remova o
333
+ ajuste. Quem lia `valor` e tratava o campo ausente precisa tratar também `null` (valor ausente no SGP).
334
+
335
+ ## Roteiro sugerido
336
+
337
+ 1. Troque a criação do cliente (`credentials`) e trate `InvalidConfigurationError` na inicialização.
338
+ 2. Renomeie os métodos pela tabela e passe os argumentos posicionais para o objeto de entrada.
339
+ 3. Troque `success` por `ok`, `error.status` por `response?.status`, `error.detail` por `error.sgp` e os
340
+ `switch` de `error.code` pelos códigos novos.
341
+ 4. Nas escritas, troque `outcome` por `effect` e releia o estado antes de reenviar após `"unknown"`.
342
+ 5. Substitua `omitSensitive` e as tuplas por `pick`/`toSafeLog`/`getSensitivity`.
343
+ 6. Rode a verificação de tipos: ids com marca e chaves desconhecidas aparecem como erros de
344
+ compilação ou como `INVALID_INPUT`.