feat(sdk): add typescript types actionable errors and mock server tests
This commit is contained in:
+75
-11
@@ -9,29 +9,66 @@ import {
|
||||
ApplicationNotAuthorizedError,
|
||||
UserCancelledError,
|
||||
CertificateNotFoundError,
|
||||
CertificateExpiredError,
|
||||
CertificateInvalidError,
|
||||
PrivateKeyNotAvailableError,
|
||||
PinRequiredError,
|
||||
PinIncorrectError,
|
||||
TokenNotFoundError,
|
||||
RequestExpiredError,
|
||||
ReplayDetectedError
|
||||
ReplayDetectedError,
|
||||
InvalidOriginError,
|
||||
UnsupportedAlgorithmError,
|
||||
ProviderNotAvailableError,
|
||||
SignatureFailedError,
|
||||
TimeoutError
|
||||
} from './errors.js';
|
||||
|
||||
import { PdfStampPicker } from './pdf-stamp-picker.js';
|
||||
import { PdfSealDesigner } from './pdf-seal-designer.js';
|
||||
|
||||
export { PdfStampPicker, PdfSealDesigner };
|
||||
export {
|
||||
PdfStampPicker,
|
||||
PdfSealDesigner,
|
||||
CyberCoreError,
|
||||
AgentNotRunningError,
|
||||
ApplicationNotAuthorizedError,
|
||||
UserCancelledError,
|
||||
CertificateNotFoundError,
|
||||
CertificateExpiredError,
|
||||
CertificateInvalidError,
|
||||
PrivateKeyNotAvailableError,
|
||||
PinRequiredError,
|
||||
PinIncorrectError,
|
||||
TokenNotFoundError,
|
||||
RequestExpiredError,
|
||||
ReplayDetectedError,
|
||||
InvalidOriginError,
|
||||
UnsupportedAlgorithmError,
|
||||
ProviderNotAvailableError,
|
||||
SignatureFailedError,
|
||||
TimeoutError
|
||||
};
|
||||
|
||||
export class CyberCoreSigner {
|
||||
/**
|
||||
* Inicializa o cliente do SDK.
|
||||
*
|
||||
* @param {Object} options Configurações do SDK.
|
||||
* @param {string} [options.baseUrl='http://127.0.0.1:21325'] URL base do agente local.
|
||||
* @param {string} [options.applicationId] UUID único da aplicação web (gerado se não fornecido).
|
||||
* @param {Object} [options={}] Configurações do SDK.
|
||||
* @param {string} [options.baseUrl] URL base completa do agente local (prevalece sobre host e port).
|
||||
* @param {string} [options.host='127.0.0.1'] Host do agente local.
|
||||
* @param {number} [options.port=21325] Porta HTTP do agente local.
|
||||
* @param {number} [options.timeoutMs=30000] Timeout padrão das operações em milissegundos.
|
||||
* @param {string} [options.applicationId] UUID único da aplicação web (gerado e persistido se omitido).
|
||||
* @param {string} [options.applicationName] Nome legível da aplicação apresentado ao usuário.
|
||||
*/
|
||||
constructor(options = {}) {
|
||||
this.baseUrl = (options.baseUrl || 'http://127.0.0.1:21325').replace(/\/+$/, '');
|
||||
const host = options.host || '127.0.0.1';
|
||||
const port = options.port !== undefined ? options.port : 21325;
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.baseUrl = (options.baseUrl || `http://${host}:${port}`).replace(/\/+$/, '');
|
||||
this.timeoutMs = options.timeoutMs !== undefined ? options.timeoutMs : 30000;
|
||||
this.applicationId = options.applicationId || this._getOrCreateApplicationId();
|
||||
this.applicationName = options.applicationName || (typeof document !== 'undefined' ? document.title : 'Aplicação Web');
|
||||
this.connected = false;
|
||||
@@ -63,8 +100,15 @@ export class CyberCoreSigner {
|
||||
const resp = await this._fetch('/ccsp/v1/status', { method: 'GET', timeoutMs });
|
||||
return resp;
|
||||
} catch (err) {
|
||||
if (err.name === 'AbortError' || err.message?.includes('Failed to fetch') || err.message?.includes('NetworkError')) {
|
||||
throw new AgentNotRunningError();
|
||||
if (
|
||||
err.name === 'AbortError' ||
|
||||
err instanceof TimeoutError ||
|
||||
err instanceof AgentNotRunningError ||
|
||||
err.message?.includes('Failed to fetch') ||
|
||||
err.message?.includes('NetworkError') ||
|
||||
err.code === 'ECONNREFUSED'
|
||||
) {
|
||||
throw new AgentNotRunningError(undefined, { host: this.host, port: this.port });
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
@@ -702,7 +746,7 @@ export class CyberCoreSigner {
|
||||
*/
|
||||
async _fetch(endpoint, options = {}) {
|
||||
const url = `${this.baseUrl}${endpoint}`;
|
||||
const timeout = options.timeoutMs || 15000;
|
||||
const timeout = options.timeoutMs !== undefined ? options.timeoutMs : (this.timeoutMs || 30000);
|
||||
const controller = typeof AbortController !== 'undefined' ? new AbortController() : null;
|
||||
const timeoutId = controller ? setTimeout(() => controller.abort(), timeout) : null;
|
||||
|
||||
@@ -738,12 +782,15 @@ export class CyberCoreSigner {
|
||||
return data;
|
||||
} catch (err) {
|
||||
if (err.name === 'AbortError') {
|
||||
throw new CyberCoreError(`Tempo limite esgotado (${timeout}ms) na comunicação com o agente.`, 'TIMEOUT_ERROR');
|
||||
throw new TimeoutError(`Tempo limite esgotado (${timeout}ms) na comunicação com o agente local.`);
|
||||
}
|
||||
if (err instanceof CyberCoreError) {
|
||||
throw err;
|
||||
}
|
||||
throw new AgentNotRunningError(`Falha ao conectar com o CyberCore Signer em ${this.baseUrl}: ${err.message}`);
|
||||
throw new AgentNotRunningError(
|
||||
`Falha ao conectar com o CyberCore Signer em ${this.baseUrl}: ${err.message}`,
|
||||
{ host: this.host, port: this.port }
|
||||
);
|
||||
} finally {
|
||||
if (timeoutId) {
|
||||
clearTimeout(timeoutId);
|
||||
@@ -829,6 +876,12 @@ export class CyberCoreSigner {
|
||||
throw new UserCancelledError(message);
|
||||
case 'CERTIFICATE_NOT_FOUND':
|
||||
throw new CertificateNotFoundError(message);
|
||||
case 'CERTIFICATE_EXPIRED':
|
||||
throw new CertificateExpiredError(message);
|
||||
case 'CERTIFICATE_INVALID':
|
||||
throw new CertificateInvalidError(message);
|
||||
case 'PRIVATE_KEY_NOT_AVAILABLE':
|
||||
throw new PrivateKeyNotAvailableError(message);
|
||||
case 'APPLICATION_NOT_AUTHORIZED':
|
||||
throw new ApplicationNotAuthorizedError(message);
|
||||
case 'PIN_REQUIRED':
|
||||
@@ -836,11 +889,22 @@ export class CyberCoreSigner {
|
||||
case 'PIN_INCORRECT':
|
||||
throw new PinIncorrectError(message);
|
||||
case 'TOKEN_NOT_FOUND':
|
||||
case 'TOKEN_REMOVED':
|
||||
throw new TokenNotFoundError(message);
|
||||
case 'REQUEST_EXPIRED':
|
||||
throw new RequestExpiredError(message);
|
||||
case 'REPLAY_DETECTED':
|
||||
throw new ReplayDetectedError(message);
|
||||
case 'INVALID_ORIGIN':
|
||||
throw new InvalidOriginError(message);
|
||||
case 'UNSUPPORTED_ALGORITHM':
|
||||
throw new UnsupportedAlgorithmError(message);
|
||||
case 'PROVIDER_NOT_AVAILABLE':
|
||||
throw new ProviderNotAvailableError(message);
|
||||
case 'SIGNATURE_FAILED':
|
||||
throw new SignatureFailedError(message);
|
||||
case 'TIMEOUT_ERROR':
|
||||
throw new TimeoutError(message);
|
||||
default:
|
||||
throw new CyberCoreError(message || `Erro do protocolo: ${code}`, code);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user