Paquete @zafirox/client-sdk (ESM, TypeScript). Todo se importa desde index.js. Esta página describe el SDK actualizado en el repositorio; el CDN 1.1.0 actualmente publicado todavía contiene la antigua creación v1. La versión nueva se publicará después del backend v2.
ZafiroxClient
new ZafiroxClient(options: ZafiroxClientOptions)| Opción | Tipo | Por defecto | Detalle |
|---|---|---|---|
baseUrl | string | — | Origen de la API, https://datacenterv2.joyeriazafirox.com |
tokenProvider | TokenProvider | — | Quien entrega el access token |
fetch | FetchLike | globalThis.fetch | Implementación de fetch a usar |
timeoutMs | number | 15000 | Timeout por petición (AbortController) |
apiVersion | string | '1' | Versión esperada para lecturas v1; orders.create() valida v2 por separado |
retry | { maxAttempts?, backoffMs?, maxRetryAfterMs? } | 2, 250, 5000 | Política de reintentos |
maxResponseBytes | number | 1048576 | Tamaño máximo aceptado de respuesta |
onRequestId | (id: string) => void | — | Recibe el X-Request-Id de cada respuesta |
Propiedades: orders, account, portfolio, apiVersion.
Proveedores de token
createClientCredentialsProvider({
tokenUrl, clientId, clientSecret, scope?, fetch?, timeoutMs?, refreshSkewSeconds?,
}): TokenProvider
createStaticTokenProvider(accessToken: string): TokenProvider
createAuthorizationCodeProvider({
apiUrl, clientId, redirectUri, scope, clientSecret?, storage?, storageKey?,
fetch?, timeoutMs?, refreshSkewSeconds?, now?, randomBytes?, sha256?,
}): AuthorizationCodeProvider
interface TokenProvider { getAccessToken(): Promise<string>; }
interface AuthorizationCodeProvider extends TokenProvider {
createAuthorizationUrl(options?: { state?, loginHint?, prompt?: 'select_account' | 'login' }): Promise<string>;
login(options?): Promise<void>; // sólo navegador: redirige
completeLogin(callbackUrl: string | URL): Promise<AuthorizationCodeSession>;
isAuthenticated(): boolean;
session(): AuthorizationCodeSession | null; // { scope, expiresAt, hasRefreshToken }
logout(): void;
}createClientCredentialsProvider es sólo para backends; cachea el token, lo renueva refreshSkewSeconds (30) antes de expirar y mantiene una única renovación en vuelo. Un rechazo del token endpoint lanza AuthenticationError con el error_code del catálogo.
createAuthorizationCodeProvider implementa «Acceder con Zafirox» (Authorization Code + PKCE S256): genera code_verifier y state, los guarda en storage (sessionStorage en el navegador, memoria en Node), redirige a GET /oauth/authorize, canjea el code en completeLogin y renueva con refresh_token (rotación) cuando el access token expira. Errores de completeLogin: access_denied, STATE_MISMATCH, AUTHORIZATION_NOT_PENDING, INVALID_CALLBACK; un refresh rechazado (INVALID_GRANT) borra la sesión local. clientSecret sólo en servidores (cliente confidencial, HTTP Basic). También se exportan generatePkce(), base64UrlEncode() y requestToken() para flujos a medida.
client.orders
orders.create(input: CreateOrderInput, options?: { idempotencyKey?: string }): Promise<OrderCreationResult> // POST /api/v2/client/orders
orders.list(query?: OrderListQuery): Promise<Page<Order>>CreateOrderInput: initialDate, deliveryDate, jewel, performedBy?, orderSubjectUid?, urgentAuthorizationCode?. JewelInput: campos requeridos customerId, customer, phone, type, material, designRefs; opcionales invoiceName, goldType, goldQuality, style, observations, details, requires3dDesign, nona, individualWeight, nonaGender, measurementSystem, measurements, widths, marking, weight, stones. Los pesos y anchos decimales son cadenas exactas. designRefs contiene de 1 a 5 referencias opacas devueltas por POST /api/v2/client/order-designs; el SDK no ofrece carga de archivos ni edición de órdenes.
orders.create() mapea camelCase a snake_case, aplica el perfil generado external-create-v2, adjunta policy_version y policy_sha256, y compara esa identidad con meta de la respuesta. Si el payload infringe el contrato, lanza OrderPolicyInputError con violations, field, code y ruleId antes de enviar. Una versión de política no conocida por el backend responde 409 order_policy.version. orders.list() sigue en GET /api/v1/client/orders.
// Para la nueva versión del SDK, después de publicar backend v2 y obtener una referencia autorizada:
const receipt = await client.orders.create({
initialDate: '2026-10-01', deliveryDate: '2026-10-15',
jewel: {
customerId: '123456789', customer: 'Cliente Demo', phone: '3000000000',
type: 'Anillo', material: 'Plata', designRefs: [authorizedDesignRef],
},
}, { idempotencyKey: 'erp-orden-123' });
console.log(receipt.serial, receipt.policyVersion, receipt.policySha256);ORDER_POLICY_VERSION, ORDER_POLICY_SHA256, ORDER_POLICY_MANIFEST y los evaluadores generados también se exportan para inspección. Su versión es independiente de la versión HTTP y del dataSchemaVersion histórico de Angular. OrderListQuery: cursor?, limit?, status?, category?, search?, startDate?, endDate?, subjectUid?.
client.account
account.get(): Promise<Account>
account.transactions(query?: TransactionQuery): Promise<Page<AccountTransaction>>TransactionQuery: cursor?, limit?, type?, from?, to?.
client.portfolio
portfolio.get(query?: PortfolioQuery): Promise<Page<PortfolioItem>>
portfolio.payments(query?: PaymentQuery): Promise<Page<Payment>>PortfolioQuery: cursor?, limit?, status?, orderSerial?, subjectUid?. PaymentQuery: cursor?, limit?, orderSerial?, from?, to?, subjectUid?.
Tipos de resultado
interface Page<T> { items: readonly T[]; nextCursor: string | null; hasMore: boolean; requestId: string; }
type DecimalString = string; // "150000.00" histórico o "0.0001" COP operativo
type CivilDate = string; // "2026-09-20"
type Rfc3339Instant = string; // "2026-09-15T17:00:00-05:00"
interface Order { serial; subjectUid; status; customer; invoiceName; jewelType; initialDate; deliveryDate; price: DecimalString; currency; performedBy }
interface OrderCreationResult { serial; subjectUid; status; replayed: boolean; initialDate; deliveryDate; requestId; policyVersion; policySha256 }
interface Account { accountId; uid; balance: DecimalString; currency; status; createdAt: Rfc3339Instant | null; updatedAt }
interface AccountTransaction { transactionId; accountId; subaccountId; type; amount; balanceBefore; balanceAfter; description; reference; occurredAt; currency }
interface PortfolioItem { orderSerial; subjectUid; status; customer; description; orderTotal; paidTotal; balance; currency; updatedAt }
interface Payment { paymentId; subjectUid; orderSerials: readonly string[]; amount; currency; paymentType; reference; occurredAt }Los campos camelCase del SDK corresponden uno a uno a los snake_case del contrato HTTP.
Errores
ZafiroxApiError y sus subclases (AuthenticationError, AuthorizationError, NotFoundError, ConflictError, ValidationError, RateLimitError, UpstreamError, TransportError) con code, status, requestId, retryable, field, diagnosticId, retryAfterSeconds. El rechazo local de creación es OrderPolicyInputError; un rechazo de servidor conserva errors[0].code y field. Ver errores y reintentos.
Transporte de bajo nivel
ApiTransport es público para quien necesite llamar una ruta nueva antes de que el SDK la exponga:
const transport = new ApiTransport({ baseUrl, tokenProvider });
const { data, meta, requestId } = await transport.request({
method: 'GET', path: '/api/v1/client/account', idempotent: true,
});Valida el envelope y la api_version, aplica timeout, límite de tamaño y reintentos igual que los módulos de alto nivel.
Utilidades
generateRequestId() devuelve un identificador válido para X-Request-Id (sdk-<uuid>); CLIENT_API_BASE_PATH es '/api/v1/client' y CLIENT_ORDER_CREATE_V2_PATH es '/api/v2/client/orders'.