Commit de7d4ad for jssip.net
commit de7d4ad7d721cc90c977073fe572482725201860
Author: José Luis Millán <jmillan@aliax.net>
Date: Tue Oct 20 11:23:10 2026 +0200
TS: move Timers, Logger, Exceptions, Constants
Move some files from JS to TS.
diff --git a/src/Constants.d.ts b/src/Constants.d.ts
deleted file mode 100644
index b12d171..0000000
--- a/src/Constants.d.ts
+++ /dev/null
@@ -1,68 +0,0 @@
-export const USER_AGENT: string;
-export const SIP = 'sip';
-export const SIPS = 'sips';
-
-export declare enum causes {
- CONNECTION_ERROR = 'Connection Error',
- REQUEST_TIMEOUT = 'Request Timeout',
- SIP_FAILURE_CODE = 'SIP Failure Code',
- INTERNAL_ERROR = 'Internal Error',
- BUSY = 'Busy',
- REJECTED = 'Rejected',
- REDIRECTED = 'Redirected',
- UNAVAILABLE = 'Unavailable',
- NOT_FOUND = 'Not Found',
- ADDRESS_INCOMPLETE = 'Address Incomplete',
- INCOMPATIBLE_SDP = 'Incompatible SDP',
- MISSING_SDP = 'Missing SDP',
- AUTHENTICATION_ERROR = 'Authentication Error',
- BYE = 'Terminated',
- WEBRTC_ERROR = 'WebRTC Error',
- CANCELED = 'Canceled',
- NO_ANSWER = 'No Answer',
- EXPIRES = 'Expires',
- NO_ACK = 'No ACK',
- DIALOG_ERROR = 'Dialog Error',
- USER_DENIED_MEDIA_ACCESS = 'User Denied Media Access',
- BAD_MEDIA_DESCRIPTION = 'Bad Media Description',
- RTP_TIMEOUT = 'RTP Timeout',
-}
-
-export const SIP_ERROR_CAUSES: {
- REDIRECTED: [300, 301, 302, 305, 380];
- BUSY: [486, 600];
- REJECTED: [403, 603];
- NOT_FOUND: [404, 604];
- UNAVAILABLE: [480, 410, 408, 430];
- ADDRESS_INCOMPLETE: [484, 424];
- INCOMPATIBLE_SDP: [488, 606];
- AUTHENTICATION_ERROR: [401, 407];
-};
-export const ACK = 'ACK';
-export const BYE = 'BYE';
-export const CANCEL = 'CANCEL';
-export const INFO = 'INFO';
-export const INVITE = 'INVITE';
-export const MESSAGE = 'MESSAGE';
-export const NOTIFY = 'NOTIFY';
-export const OPTIONS = 'OPTIONS';
-export const REGISTER = 'REGISTER';
-export const REFER = 'REFER';
-export const UPDATE = 'UPDATE';
-export const SUBSCRIBE = 'SUBSCRIBE';
-
-export declare enum DTMF_TRANSPORT {
- // eslint-disable-next-line no-shadow
- INFO = 'INFO',
- RFC2833 = 'RFC2833',
-}
-
-export const REASON_PHRASE: Record<number, string>;
-export const ALLOWED_METHODS =
- 'INVITE,ACK,CANCEL,BYE,UPDATE,MESSAGE,OPTIONS,REFER,INFO,NOTIFY,SUBSCRIBE';
-export const ACCEPTED_BODY_TYPES = 'application/sdp, application/dtmf-relay';
-export const MAX_FORWARDS = 69;
-export const SESSION_EXPIRES = 90;
-export const MIN_SESSION_EXPIRES = 60;
-export const CONNECTION_RECOVERY_MAX_INTERVAL = 30;
-export const CONNECTION_RECOVERY_MIN_INTERVAL = 2;
diff --git a/src/Constants.js b/src/Constants.js
deleted file mode 100644
index 0212f56..0000000
--- a/src/Constants.js
+++ /dev/null
@@ -1,160 +0,0 @@
-const pkg = require('../package.json');
-
-module.exports = {
- USER_AGENT: `${pkg.title} ${pkg.version}`,
-
- // SIP scheme.
- SIP: 'sip',
- SIPS: 'sips',
-
- // End and Failure causes.
- causes: {
- // Generic error causes.
- CONNECTION_ERROR: 'Connection Error',
- REQUEST_TIMEOUT: 'Request Timeout',
- SIP_FAILURE_CODE: 'SIP Failure Code',
- INTERNAL_ERROR: 'Internal Error',
-
- // SIP error causes.
- BUSY: 'Busy',
- REJECTED: 'Rejected',
- REDIRECTED: 'Redirected',
- UNAVAILABLE: 'Unavailable',
- NOT_FOUND: 'Not Found',
- ADDRESS_INCOMPLETE: 'Address Incomplete',
- INCOMPATIBLE_SDP: 'Incompatible SDP',
- MISSING_SDP: 'Missing SDP',
- AUTHENTICATION_ERROR: 'Authentication Error',
-
- // Session error causes.
- BYE: 'Terminated',
- WEBRTC_ERROR: 'WebRTC Error',
- CANCELED: 'Canceled',
- NO_ANSWER: 'No Answer',
- EXPIRES: 'Expires',
- NO_ACK: 'No ACK',
- DIALOG_ERROR: 'Dialog Error',
- USER_DENIED_MEDIA_ACCESS: 'User Denied Media Access',
- BAD_MEDIA_DESCRIPTION: 'Bad Media Description',
- RTP_TIMEOUT: 'RTP Timeout',
- },
-
- SIP_ERROR_CAUSES: {
- REDIRECTED: [300, 301, 302, 305, 380],
- BUSY: [486, 600],
- REJECTED: [403, 603],
- NOT_FOUND: [404, 604],
- UNAVAILABLE: [480, 410, 408, 430],
- ADDRESS_INCOMPLETE: [484, 424],
- INCOMPATIBLE_SDP: [488, 606],
- AUTHENTICATION_ERROR: [401, 407],
- },
-
- // SIP Methods.
- ACK: 'ACK',
- BYE: 'BYE',
- CANCEL: 'CANCEL',
- INFO: 'INFO',
- INVITE: 'INVITE',
- MESSAGE: 'MESSAGE',
- NOTIFY: 'NOTIFY',
- OPTIONS: 'OPTIONS',
- REGISTER: 'REGISTER',
- REFER: 'REFER',
- UPDATE: 'UPDATE',
- SUBSCRIBE: 'SUBSCRIBE',
-
- // DTMF transport methods.
- DTMF_TRANSPORT: {
- INFO: 'INFO',
- RFC2833: 'RFC2833',
- },
-
- /* SIP Response Reasons
- * DOC: https://www.iana.org/assignments/sip-parameters
- * Copied from https://github.com/versatica/OverSIP/blob/master/lib/oversip/sip/constants.rb#L7
- */
- REASON_PHRASE: {
- 100: 'Trying',
- 180: 'Ringing',
- 181: 'Call Is Being Forwarded',
- 182: 'Queued',
- 183: 'Session Progress',
- 199: 'Early Dialog Terminated', // draft-ietf-sipcore-199
- 200: 'OK',
- 202: 'Accepted', // RFC 3265
- 204: 'No Notification', // RFC 5839
- 300: 'Multiple Choices',
- 301: 'Moved Permanently',
- 302: 'Moved Temporarily',
- 305: 'Use Proxy',
- 380: 'Alternative Service',
- 400: 'Bad Request',
- 401: 'Unauthorized',
- 402: 'Payment Required',
- 403: 'Forbidden',
- 404: 'Not Found',
- 405: 'Method Not Allowed',
- 406: 'Not Acceptable',
- 407: 'Proxy Authentication Required',
- 408: 'Request Timeout',
- 410: 'Gone',
- 412: 'Conditional Request Failed', // RFC 3903
- 413: 'Request Entity Too Large',
- 414: 'Request-URI Too Long',
- 415: 'Unsupported Media Type',
- 416: 'Unsupported URI Scheme',
- 417: 'Unknown Resource-Priority', // RFC 4412
- 420: 'Bad Extension',
- 421: 'Extension Required',
- 422: 'Session Interval Too Small', // RFC 4028
- 423: 'Interval Too Brief',
- 424: 'Bad Location Information', // RFC 6442
- 428: 'Use Identity Header', // RFC 4474
- 429: 'Provide Referrer Identity', // RFC 3892
- 430: 'Flow Failed', // RFC 5626
- 433: 'Anonymity Disallowed', // RFC 5079
- 436: 'Bad Identity-Info', // RFC 4474
- 437: 'Unsupported Certificate', // RFC 4744
- 438: 'Invalid Identity Header', // RFC 4744
- 439: 'First Hop Lacks Outbound Support', // RFC 5626
- 440: 'Max-Breadth Exceeded', // RFC 5393
- 469: 'Bad Info Package', // draft-ietf-sipcore-info-events
- 470: 'Consent Needed', // RFC 5360
- 478: 'Unresolvable Destination', // Custom code copied from Kamailio.
- 480: 'Temporarily Unavailable',
- 481: 'Call/Transaction Does Not Exist',
- 482: 'Loop Detected',
- 483: 'Too Many Hops',
- 484: 'Address Incomplete',
- 485: 'Ambiguous',
- 486: 'Busy Here',
- 487: 'Request Terminated',
- 488: 'Not Acceptable Here',
- 489: 'Bad Event', // RFC 3265
- 491: 'Request Pending',
- 493: 'Undecipherable',
- 494: 'Security Agreement Required', // RFC 3329
- 500: 'JsSIP Internal Error',
- 501: 'Not Implemented',
- 502: 'Bad Gateway',
- 503: 'Service Unavailable',
- 504: 'Server Time-out',
- 505: 'Version Not Supported',
- 513: 'Message Too Large',
- 580: 'Precondition Failure', // RFC 3312
- 600: 'Busy Everywhere',
- 603: 'Decline',
- 604: 'Does Not Exist Anywhere',
- 606: 'Not Acceptable',
- },
-
- ALLOWED_METHODS:
- 'INVITE,ACK,CANCEL,BYE,UPDATE,MESSAGE,OPTIONS,REFER,INFO,NOTIFY,SUBSCRIBE',
- ACCEPTED_BODY_TYPES: 'application/sdp, application/dtmf-relay',
- MAX_FORWARDS: 69,
- SESSION_EXPIRES: 90,
- MIN_SESSION_EXPIRES: 60,
- CONNECTION_RECOVERY_MAX_INTERVAL: 30,
- CONNECTION_RECOVERY_MIN_INTERVAL: 2,
-};
diff --git a/src/Constants.ts b/src/Constants.ts
new file mode 100644
index 0000000..df84da3
--- /dev/null
+++ b/src/Constants.ts
@@ -0,0 +1,163 @@
+// `package.json` lives outside `rootDir` so it cannot be `import`ed. A plain
+// `require()` is not resolved by TypeScript against `rootDir`, so it is used
+// here instead.
+// eslint-disable-next-line @typescript-eslint/no-require-imports
+const pkg = require('../package.json') as { title: string; version: string };
+
+export const USER_AGENT = `${pkg.title} ${pkg.version}`;
+
+// SIP scheme.
+export const SIP = 'sip';
+export const SIPS = 'sips';
+
+// End and Failure causes.
+export enum causes {
+ // Generic error causes.
+ CONNECTION_ERROR = 'Connection Error',
+ REQUEST_TIMEOUT = 'Request Timeout',
+ SIP_FAILURE_CODE = 'SIP Failure Code',
+ INTERNAL_ERROR = 'Internal Error',
+
+ // SIP error causes.
+ BUSY = 'Busy',
+ REJECTED = 'Rejected',
+ REDIRECTED = 'Redirected',
+ UNAVAILABLE = 'Unavailable',
+ NOT_FOUND = 'Not Found',
+ ADDRESS_INCOMPLETE = 'Address Incomplete',
+ INCOMPATIBLE_SDP = 'Incompatible SDP',
+ MISSING_SDP = 'Missing SDP',
+ AUTHENTICATION_ERROR = 'Authentication Error',
+
+ // Session error causes.
+ BYE = 'Terminated',
+ WEBRTC_ERROR = 'WebRTC Error',
+ CANCELED = 'Canceled',
+ NO_ANSWER = 'No Answer',
+ EXPIRES = 'Expires',
+ NO_ACK = 'No ACK',
+ DIALOG_ERROR = 'Dialog Error',
+ USER_DENIED_MEDIA_ACCESS = 'User Denied Media Access',
+ BAD_MEDIA_DESCRIPTION = 'Bad Media Description',
+ RTP_TIMEOUT = 'RTP Timeout',
+}
+
+export const SIP_ERROR_CAUSES: Record<string, number[]> = {
+ REDIRECTED: [300, 301, 302, 305, 380],
+ BUSY: [486, 600],
+ REJECTED: [403, 603],
+ NOT_FOUND: [404, 604],
+ UNAVAILABLE: [480, 410, 408, 430],
+ ADDRESS_INCOMPLETE: [484, 424],
+ INCOMPATIBLE_SDP: [488, 606],
+ AUTHENTICATION_ERROR: [401, 407],
+};
+
+// SIP Methods.
+export const ACK = 'ACK';
+export const BYE = 'BYE';
+export const CANCEL = 'CANCEL';
+export const INFO = 'INFO';
+export const INVITE = 'INVITE';
+export const MESSAGE = 'MESSAGE';
+export const NOTIFY = 'NOTIFY';
+export const OPTIONS = 'OPTIONS';
+export const REGISTER = 'REGISTER';
+export const REFER = 'REFER';
+export const UPDATE = 'UPDATE';
+export const SUBSCRIBE = 'SUBSCRIBE';
+
+// DTMF transport methods.
+export enum DTMF_TRANSPORT {
+ // eslint-disable-next-line no-shadow
+ INFO = 'INFO',
+ RFC2833 = 'RFC2833',
+}
+
+/* SIP Response Reasons
+ * DOC: https://www.iana.org/assignments/sip-parameters
+ * Copied from https://github.com/versatica/OverSIP/blob/master/lib/oversip/sip/constants.rb#L7
+ */
+export const REASON_PHRASE: Record<number, string> = {
+ 100: 'Trying',
+ 180: 'Ringing',
+ 181: 'Call Is Being Forwarded',
+ 182: 'Queued',
+ 183: 'Session Progress',
+ 199: 'Early Dialog Terminated', // draft-ietf-sipcore-199
+ 200: 'OK',
+ 202: 'Accepted', // RFC 3265
+ 204: 'No Notification', // RFC 5839
+ 300: 'Multiple Choices',
+ 301: 'Moved Permanently',
+ 302: 'Moved Temporarily',
+ 305: 'Use Proxy',
+ 380: 'Alternative Service',
+ 400: 'Bad Request',
+ 401: 'Unauthorized',
+ 402: 'Payment Required',
+ 403: 'Forbidden',
+ 404: 'Not Found',
+ 405: 'Method Not Allowed',
+ 406: 'Not Acceptable',
+ 407: 'Proxy Authentication Required',
+ 408: 'Request Timeout',
+ 410: 'Gone',
+ 412: 'Conditional Request Failed', // RFC 3903
+ 413: 'Request Entity Too Large',
+ 414: 'Request-URI Too Long',
+ 415: 'Unsupported Media Type',
+ 416: 'Unsupported URI Scheme',
+ 417: 'Unknown Resource-Priority', // RFC 4412
+ 420: 'Bad Extension',
+ 421: 'Extension Required',
+ 422: 'Session Interval Too Small', // RFC 4028
+ 423: 'Interval Too Brief',
+ 424: 'Bad Location Information', // RFC 6442
+ 428: 'Use Identity Header', // RFC 4474
+ 429: 'Provide Referrer Identity', // RFC 3892
+ 430: 'Flow Failed', // RFC 5626
+ 433: 'Anonymity Disallowed', // RFC 5079
+ 436: 'Bad Identity-Info', // RFC 4474
+ 437: 'Unsupported Certificate', // RFC 4744
+ 438: 'Invalid Identity Header', // RFC 4744
+ 439: 'First Hop Lacks Outbound Support', // RFC 5626
+ 440: 'Max-Breadth Exceeded', // RFC 5393
+ 469: 'Bad Info Package', // draft-ietf-sipcore-info-events
+ 470: 'Consent Needed', // RFC 5360
+ 478: 'Unresolvable Destination', // Custom code copied from Kamailio.
+ 480: 'Temporarily Unavailable',
+ 481: 'Call/Transaction Does Not Exist',
+ 482: 'Loop Detected',
+ 483: 'Too Many Hops',
+ 484: 'Address Incomplete',
+ 485: 'Ambiguous',
+ 486: 'Busy Here',
+ 487: 'Request Terminated',
+ 488: 'Not Acceptable Here',
+ 489: 'Bad Event', // RFC 3265
+ 491: 'Request Pending',
+ 493: 'Undecipherable',
+ 494: 'Security Agreement Required', // RFC 3329
+ 500: 'JsSIP Internal Error',
+ 501: 'Not Implemented',
+ 502: 'Bad Gateway',
+ 503: 'Service Unavailable',
+ 504: 'Server Time-out',
+ 505: 'Version Not Supported',
+ 513: 'Message Too Large',
+ 580: 'Precondition Failure', // RFC 3312
+ 600: 'Busy Everywhere',
+ 603: 'Decline',
+ 604: 'Does Not Exist Anywhere',
+ 606: 'Not Acceptable',
+};
+
+export const ALLOWED_METHODS =
+ 'INVITE,ACK,CANCEL,BYE,UPDATE,MESSAGE,OPTIONS,REFER,INFO,NOTIFY,SUBSCRIBE';
+export const ACCEPTED_BODY_TYPES = 'application/sdp, application/dtmf-relay';
+export const MAX_FORWARDS = 69;
+export const SESSION_EXPIRES = 90;
+export const MIN_SESSION_EXPIRES = 60;
+export const CONNECTION_RECOVERY_MAX_INTERVAL = 30;
+export const CONNECTION_RECOVERY_MIN_INTERVAL = 2;
diff --git a/src/Dialog.js b/src/Dialog.js
index 6b72c62..70ec586 100644
--- a/src/Dialog.js
+++ b/src/Dialog.js
@@ -1,4 +1,4 @@
-const Logger = require('./Logger');
+const { Logger } = require('./Logger');
const SIPMessage = require('./SIPMessage');
const JsSIP_C = require('./Constants');
const Transactions = require('./Transactions');
diff --git a/src/DigestAuthentication.js b/src/DigestAuthentication.js
index 4758cad..fb90d81 100644
--- a/src/DigestAuthentication.js
+++ b/src/DigestAuthentication.js
@@ -1,4 +1,4 @@
-const Logger = require('./Logger');
+const { Logger } = require('./Logger');
const Utils = require('./Utils');
const logger = new Logger('DigestAuthentication');
diff --git a/src/Exceptions.d.ts b/src/Exceptions.d.ts
deleted file mode 100644
index 818bf4a..0000000
--- a/src/Exceptions.d.ts
+++ /dev/null
@@ -1,26 +0,0 @@
-declare class BaseError extends Error {
- code: number;
-}
-
-export class ConfigurationError extends BaseError {
- parameter: string;
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- value: any;
-
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- constructor(parameter: string, value?: any);
-}
-
-export class InvalidStateError extends BaseError {
- status: number;
-
- constructor(status: number);
-}
-
-export class NotSupportedError extends BaseError {
- constructor(message: string);
-}
-
-export class NotReadyError extends BaseError {
- constructor(message: string);
-}
diff --git a/src/Exceptions.js b/src/Exceptions.js
deleted file mode 100644
index 00d9ebc..0000000
--- a/src/Exceptions.js
+++ /dev/null
@@ -1,51 +0,0 @@
-class ConfigurationError extends Error {
- constructor(parameter, value) {
- super();
-
- this.code = 1;
- this.name = 'CONFIGURATION_ERROR';
- this.parameter = parameter;
- this.value = value;
- this.message = !this.value
- ? `Missing parameter: ${this.parameter}`
- : `Invalid value ${JSON.stringify(this.value)} for parameter "${this.parameter}"`;
- }
-}
-
-class InvalidStateError extends Error {
- constructor(status) {
- super();
-
- this.code = 2;
- this.name = 'INVALID_STATE_ERROR';
- this.status = status;
- this.message = `Invalid status: ${status}`;
- }
-}
-
-class NotSupportedError extends Error {
- constructor(message) {
- super();
-
- this.code = 3;
- this.name = 'NOT_SUPPORTED_ERROR';
- this.message = message;
- }
-}
-
-class NotReadyError extends Error {
- constructor(message) {
- super();
-
- this.code = 4;
- this.name = 'NOT_READY_ERROR';
- this.message = message;
- }
-}
-
-module.exports = {
- ConfigurationError,
- InvalidStateError,
- NotSupportedError,
- NotReadyError,
-};
diff --git a/src/Exceptions.ts b/src/Exceptions.ts
new file mode 100644
index 0000000..16e736e
--- /dev/null
+++ b/src/Exceptions.ts
@@ -0,0 +1,53 @@
+export class ConfigurationError extends Error {
+ code = 1;
+ override name = 'CONFIGURATION_ERROR';
+ parameter: string;
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ value: any;
+
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ constructor(parameter: string, value?: any) {
+ super();
+
+ this.parameter = parameter;
+ this.value = value;
+ this.message = !this.value
+ ? `Missing parameter: ${this.parameter}`
+ : `Invalid value ${JSON.stringify(this.value)} for parameter "${this.parameter}"`;
+ }
+}
+
+export class InvalidStateError extends Error {
+ code = 2;
+ override name = 'INVALID_STATE_ERROR';
+ status: number;
+
+ constructor(status: number) {
+ super();
+
+ this.status = status;
+ this.message = `Invalid status: ${status}`;
+ }
+}
+
+export class NotSupportedError extends Error {
+ code = 3;
+ override name = 'NOT_SUPPORTED_ERROR';
+
+ constructor(message: string) {
+ super();
+
+ this.message = message;
+ }
+}
+
+export class NotReadyError extends Error {
+ code = 4;
+ override name = 'NOT_READY_ERROR';
+
+ constructor(message: string) {
+ super();
+
+ this.message = message;
+ }
+}
diff --git a/src/Logger.js b/src/Logger.js
deleted file mode 100644
index 4abb8e7..0000000
--- a/src/Logger.js
+++ /dev/null
@@ -1,34 +0,0 @@
-const debug = require('debug');
-
-const APP_NAME = 'JsSIP';
-
-module.exports = class Logger {
- constructor(prefix) {
- if (prefix) {
- this._debug = debug.default(`${APP_NAME}:${prefix}`);
- this._warn = debug.default(`${APP_NAME}:WARN:${prefix}`);
- this._error = debug.default(`${APP_NAME}:ERROR:${prefix}`);
- } else {
- this._debug = debug.default(APP_NAME);
- this._warn = debug.default(`${APP_NAME}:WARN`);
- this._error = debug.default(`${APP_NAME}:ERROR`);
- }
- /* eslint-disable no-console */
- this._debug.log = console.info.bind(console);
- this._warn.log = console.warn.bind(console);
- this._error.log = console.error.bind(console);
- /* eslint-enable no-console */
- }
-
- get debug() {
- return this._debug;
- }
-
- get warn() {
- return this._warn;
- }
-
- get error() {
- return this._error;
- }
-};
diff --git a/src/Logger.ts b/src/Logger.ts
new file mode 100644
index 0000000..f9927fd
--- /dev/null
+++ b/src/Logger.ts
@@ -0,0 +1,39 @@
+import debug from 'debug';
+
+const APP_NAME = 'JsSIP';
+
+export class Logger {
+ #_debug: debug.Debugger;
+ #_warn: debug.Debugger;
+ #_error: debug.Debugger;
+
+ constructor(prefix?: string) {
+ if (prefix) {
+ this.#_debug = debug(`${APP_NAME}:${prefix}`);
+ this.#_warn = debug(`${APP_NAME}:WARN:${prefix}`);
+ this.#_error = debug(`${APP_NAME}:ERROR:${prefix}`);
+ } else {
+ this.#_debug = debug(APP_NAME);
+ this.#_warn = debug(`${APP_NAME}:WARN`);
+ this.#_error = debug(`${APP_NAME}:ERROR`);
+ }
+
+ /* eslint-disable no-console */
+ this.#_debug.log = console.info.bind(console);
+ this.#_warn.log = console.warn.bind(console);
+ this.#_error.log = console.error.bind(console);
+ /* eslint-enable no-console */
+ }
+
+ get debug(): debug.Debugger {
+ return this.#_debug;
+ }
+
+ get warn(): debug.Debugger {
+ return this.#_warn;
+ }
+
+ get error(): debug.Debugger {
+ return this.#_error;
+ }
+}
diff --git a/src/Message.js b/src/Message.js
index 801f823..1c15b7d 100644
--- a/src/Message.js
+++ b/src/Message.js
@@ -1,5 +1,5 @@
const EventEmitter = require('events').EventEmitter;
-const Logger = require('./Logger');
+const { Logger } = require('./Logger');
const JsSIP_C = require('./Constants');
const SIPMessage = require('./SIPMessage');
const Utils = require('./Utils');
diff --git a/src/Notifier.js b/src/Notifier.js
index deea8bb..0596533 100644
--- a/src/Notifier.js
+++ b/src/Notifier.js
@@ -1,6 +1,6 @@
const EventEmitter = require('events').EventEmitter;
const Exceptions = require('./Exceptions');
-const Logger = require('./Logger');
+const { Logger } = require('./Logger');
const JsSIP_C = require('./Constants');
const Utils = require('./Utils');
const Dialog = require('./Dialog');
diff --git a/src/Options.js b/src/Options.js
index f01c35d..07a70de 100644
--- a/src/Options.js
+++ b/src/Options.js
@@ -1,5 +1,5 @@
const EventEmitter = require('events').EventEmitter;
-const Logger = require('./Logger');
+const { Logger } = require('./Logger');
const JsSIP_C = require('./Constants');
const SIPMessage = require('./SIPMessage');
const Utils = require('./Utils');
diff --git a/src/Parser.js b/src/Parser.js
index 79013d9..a2e67be 100644
--- a/src/Parser.js
+++ b/src/Parser.js
@@ -1,4 +1,4 @@
-const Logger = require('./Logger');
+const { Logger } = require('./Logger');
const Grammar = require('./Grammar');
const SIPMessage = require('./SIPMessage');
diff --git a/src/RTCSession.js b/src/RTCSession.js
index 9aa40ac..97e1745 100644
--- a/src/RTCSession.js
+++ b/src/RTCSession.js
@@ -3,7 +3,7 @@
const EventEmitter = require('events').EventEmitter;
const sdp_transform = require('sdp-transform');
-const Logger = require('./Logger');
+const { Logger } = require('./Logger');
const JsSIP_C = require('./Constants');
const Exceptions = require('./Exceptions');
const Transactions = require('./Transactions');
diff --git a/src/RTCSession/DTMF.js b/src/RTCSession/DTMF.js
index abacc0f..1f96950 100644
--- a/src/RTCSession/DTMF.js
+++ b/src/RTCSession/DTMF.js
@@ -1,5 +1,5 @@
const EventEmitter = require('events').EventEmitter;
-const Logger = require('../Logger');
+const { Logger } = require('../Logger');
const JsSIP_C = require('../Constants');
const Exceptions = require('../Exceptions');
const Utils = require('../Utils');
diff --git a/src/RTCSession/ReferNotifier.js b/src/RTCSession/ReferNotifier.js
index 4af0ea0..8369e65 100644
--- a/src/RTCSession/ReferNotifier.js
+++ b/src/RTCSession/ReferNotifier.js
@@ -1,4 +1,4 @@
-const Logger = require('../Logger');
+const { Logger } = require('../Logger');
const JsSIP_C = require('../Constants');
const logger = new Logger('RTCSession:ReferNotifier');
diff --git a/src/RTCSession/ReferSubscriber.js b/src/RTCSession/ReferSubscriber.js
index 84d82e9..e8aca9b 100644
--- a/src/RTCSession/ReferSubscriber.js
+++ b/src/RTCSession/ReferSubscriber.js
@@ -1,5 +1,5 @@
const EventEmitter = require('events').EventEmitter;
-const Logger = require('../Logger');
+const { Logger } = require('../Logger');
const JsSIP_C = require('../Constants');
const Grammar = require('../Grammar');
const Utils = require('../Utils');
diff --git a/src/Registrator.js b/src/Registrator.js
index 7ce227b..0085139 100644
--- a/src/Registrator.js
+++ b/src/Registrator.js
@@ -1,4 +1,4 @@
-const Logger = require('./Logger');
+const { Logger } = require('./Logger');
const Utils = require('./Utils');
const JsSIP_C = require('./Constants');
const SIPMessage = require('./SIPMessage');
diff --git a/src/RequestSender.js b/src/RequestSender.js
index c7ddc35..50d4faa 100644
--- a/src/RequestSender.js
+++ b/src/RequestSender.js
@@ -1,4 +1,4 @@
-const Logger = require('./Logger');
+const { Logger } = require('./Logger');
const JsSIP_C = require('./Constants');
const DigestAuthentication = require('./DigestAuthentication');
const Transactions = require('./Transactions');
diff --git a/src/SIPMessage.js b/src/SIPMessage.js
index e2d205f..44b08e7 100644
--- a/src/SIPMessage.js
+++ b/src/SIPMessage.js
@@ -1,5 +1,5 @@
const sdp_transform = require('sdp-transform');
-const Logger = require('./Logger');
+const { Logger } = require('./Logger');
const JsSIP_C = require('./Constants');
const Utils = require('./Utils');
const NameAddrHeader = require('./NameAddrHeader');
diff --git a/src/Socket.js b/src/Socket.js
index e502360..5c9ffc1 100644
--- a/src/Socket.js
+++ b/src/Socket.js
@@ -1,4 +1,4 @@
-const Logger = require('./Logger');
+const { Logger } = require('./Logger');
const Utils = require('./Utils');
const Grammar = require('./Grammar');
diff --git a/src/Subscriber.js b/src/Subscriber.js
index 13f8bde..50bb0b8 100644
--- a/src/Subscriber.js
+++ b/src/Subscriber.js
@@ -1,6 +1,6 @@
const EventEmitter = require('events').EventEmitter;
const Exceptions = require('./Exceptions');
-const Logger = require('./Logger');
+const { Logger } = require('./Logger');
const JsSIP_C = require('./Constants');
const Utils = require('./Utils');
const Grammar = require('./Grammar');
diff --git a/src/Timers.js b/src/Timers.js
deleted file mode 100644
index 2af8bfa..0000000
--- a/src/Timers.js
+++ /dev/null
@@ -1,19 +0,0 @@
-const T1 = 500,
- T2 = 4000,
- T4 = 5000;
-
-module.exports = {
- T1,
- T2,
- T4,
- TIMER_B: 64 * T1,
- TIMER_D: 0 * T1,
- TIMER_F: 64 * T1,
- TIMER_H: 64 * T1,
- TIMER_I: 0 * T1,
- TIMER_J: 0 * T1,
- TIMER_K: 0 * T4,
- TIMER_L: 64 * T1,
- TIMER_M: 64 * T1,
- PROVISIONAL_RESPONSE_INTERVAL: 60000, // See RFC 3261 Section 13.3.1.1
-};
diff --git a/src/Timers.ts b/src/Timers.ts
new file mode 100644
index 0000000..563edef
--- /dev/null
+++ b/src/Timers.ts
@@ -0,0 +1,16 @@
+export const T1 = 500;
+export const T2 = 4000;
+export const T4 = 5000;
+
+export const TIMER_B = 64 * T1;
+export const TIMER_D = 0 * T1;
+export const TIMER_F = 64 * T1;
+export const TIMER_H = 64 * T1;
+export const TIMER_I = 0 * T1;
+export const TIMER_J = 0 * T1;
+export const TIMER_K = 0 * T4;
+export const TIMER_L = 64 * T1;
+export const TIMER_M = 64 * T1;
+
+// See RFC 3261 Section 13.3.1.1.
+export const PROVISIONAL_RESPONSE_INTERVAL = 60000;
diff --git a/src/Transactions.js b/src/Transactions.js
index 4978bc9..8cc73a2 100644
--- a/src/Transactions.js
+++ b/src/Transactions.js
@@ -1,5 +1,5 @@
const EventEmitter = require('events').EventEmitter;
-const Logger = require('./Logger');
+const { Logger } = require('./Logger');
const JsSIP_C = require('./Constants');
const SIPMessage = require('./SIPMessage');
const Timers = require('./Timers');
diff --git a/src/Transport.js b/src/Transport.js
index 258382c..008d335 100644
--- a/src/Transport.js
+++ b/src/Transport.js
@@ -1,4 +1,4 @@
-const Logger = require('./Logger');
+const { Logger } = require('./Logger');
const Socket = require('./Socket');
const JsSIP_C = require('./Constants');
diff --git a/src/UA.js b/src/UA.js
index 687ff37..2c51bb6 100644
--- a/src/UA.js
+++ b/src/UA.js
@@ -1,7 +1,7 @@
/* eslint-disable no-invalid-this */
const EventEmitter = require('events').EventEmitter;
-const Logger = require('./Logger');
+const { Logger } = require('./Logger');
const JsSIP_C = require('./Constants');
const Registrator = require('./Registrator');
const RTCSession = require('./RTCSession');
diff --git a/src/WebSocketInterface.js b/src/WebSocketInterface.js
index 9dc582e..852de85 100644
--- a/src/WebSocketInterface.js
+++ b/src/WebSocketInterface.js
@@ -1,4 +1,4 @@
-const Logger = require('./Logger');
+const { Logger } = require('./Logger');
const Grammar = require('./Grammar');
const logger = new Logger('WebSocketInterface');
diff --git a/src/sanityCheck.js b/src/sanityCheck.js
index ef3d661..5ff60ac 100644
--- a/src/sanityCheck.js
+++ b/src/sanityCheck.js
@@ -1,4 +1,4 @@
-const Logger = require('./Logger');
+const { Logger } = require('./Logger');
const JsSIP_C = require('./Constants');
const SIPMessage = require('./SIPMessage');
const Utils = require('./Utils');
diff --git a/tsconfig.json b/tsconfig.json
index 76528d3..cc59ba4 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -7,11 +7,11 @@
"outDir": "lib",
"rootDir": "src",
"allowJs": true,
- // Do not generate declaration files automatically yet.
- // "declaration": true,
- // "declarationMap": true,
- // "emitDeclarationOnly": false,
- // "declarationDir": "lib",
+ // Declaration files are generated for .ts sources. Modules not yet ported
+ // to TypeScript still ship the hand-written .d.ts files in src/, which
+ // npm-scripts.mjs copies over the generated ones.
+ "declaration": true,
+ "declarationMap": true,
"isolatedModules": true,
"verbatimModuleSyntax": false,
"useDefineForClassFields": true,