UNPKG

@aptpod/iscp-ts

Version:

iSCP 2.0 client library for TypeScript

895 lines 46.1 kB
"use strict"; var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) { if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it"); return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver); }; var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) { if (kind === "m") throw new TypeError("Private method is not writable"); if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter"); if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it"); return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var _Conn_instances, _Conn_nodeId, _Conn_protocolVersion, _Conn_pingInterval, _Conn_pingTimeout, _Conn_projectUuid, _Conn_tokenSource, _Conn_reqSequence, _Conn_streamSequence, _Conn_logger, _Conn_encoding, _Conn_transport, _Conn_internalUpstreamMap, _Conn_internalDownstreamMap, _Conn_metadataInternalDownstreamMap, _Conn_abortController, _Conn_wireConfig, _Conn_wire, _Conn_autoReconnect, _Conn_disconnectedEvent, _Conn_closedResolver, _Conn_connReconnectLock, _Conn_transportReconnectLock, _Conn_closeLock, _Conn_closeRequiredResolver, _Conn_downstreamReplyCallTransformStreamMap, _Conn_callEvent, _Conn_replyCallEvent, _Conn_reconnectingEvent, _Conn_reconnectedEvent, _Conn_run, _Conn_createWire, _Conn_connect, _Conn_reconnect, _Conn_handleUpstreamChunkAck, _Conn_handleDownstreamChunk, _Conn_handleDownstreamMetadata, _Conn_handleDownstreamChunkAckComplete, _Conn_handleDownstreamCall, _Conn_sendMetadata, _Conn_close; Object.defineProperty(exports, "__esModule", { value: true }); exports.Conn = exports.ReconnectingEvent = exports.DisconnectedEvent = void 0; const await_lock_1 = __importDefault(require("await-lock")); const web_streams_polyfill_1 = require("web-streams-polyfill"); const encoding_1 = require("./encoding"); const message_1 = require("./message"); const transport_1 = require("./transport"); const exceptions_1 = require("./exceptions"); const constant_1 = require("./constant"); const downstream_1 = require("./message/downstream"); const common_1 = require("./message/common"); const model_1 = require("./model"); const upstream_1 = require("./upstream"); const downstream_2 = require("./downstream"); const sequence_1 = require("./sequence"); const flush_policy_1 = require("./flush-policy"); const stream_reader_iterator_1 = require("./utils/stream-reader-iterator"); const logger_1 = require("./logger"); const message_io_1 = require("./message-io"); const wire_1 = require("./wire"); const typed_event_1 = require("./utils/typed-event"); const transport_with_reconnect_1 = require("./transport-with-reconnect"); const resolver_1 = require("./utils/resolver"); const uuid_1 = require("./utils/uuid"); const exceptions_2 = require("./exceptions/exceptions"); const PROTOCOL_VERSION = '2.0.0'; /** * iSCPを切断した時のイベントです。 * @category Connection */ class DisconnectedEvent { constructor(init) { this.error = init.error; } } exports.DisconnectedEvent = DisconnectedEvent; /** * iSCPの再接続を開始した時のイベントです。 * @category Connection */ class ReconnectingEvent { constructor(init) { this.error = init.error; } } exports.ReconnectingEvent = ReconnectingEvent; /** * iSCPのコネクションを表すクラスです。 * * @category Connection * * @attention * このクラスのオブジェクトは、必ず{@link Conn}の{@link Conn.connect}を使用して生成してください。 * * @example * ```ts * const example = async () => { * const conn = await Conn.connect(...) * try { * // ... * } finally { * await conn.close() * } * } * ``` */ class Conn { /** * iSCP接続を行い{@link Conn}を返却します。 */ static async connect(config) { const encodingName = config.encoding ?? Conn.DEFAULT_ENCODING_NAME; const negotiationParams = new transport_1.NegotiationParams(); negotiationParams.enc = encodingName; const encoding = toEncodingByName(encodingName); const conn = new Conn({ logLevel: config.logLevel, address: config.address, negotiationParams, connector: config.connector, encoding, nodeId: config.nodeId, protocolVersion: PROTOCOL_VERSION, pingInterval: config.pingInterval ?? Conn.DEFAULT_PING_INTERVAL, pingTimeout: config.pingTimeout ?? Conn.DEFAULT_PING_TIMEOUT, projectUuid: config.projectUuid, tokenSource: config.tokenSource, autoReconnect: config.autoReconnect ?? Conn.DEFAULT_AUTO_RECONNECT, reconnectBaseInterval: config.reconnectBaseInterval ?? Conn.DEFAULT_RECONNECT_BASE_INTERVAL, reconnectMaxInterval: config.reconnectMaxInterval ?? Conn.DEFAULT_RECONNECT_MAX_INTERVAL, }); await __classPrivateFieldGet(conn, _Conn_instances, "m", _Conn_run).call(conn); return conn; } /** * @internal */ constructor(config) { _Conn_instances.add(this); // from config _Conn_nodeId.set(this, void 0); _Conn_protocolVersion.set(this, void 0); _Conn_pingInterval.set(this, void 0); _Conn_pingTimeout.set(this, void 0); _Conn_projectUuid.set(this, void 0); _Conn_tokenSource.set(this, void 0); // sequence _Conn_reqSequence.set(this, void 0); _Conn_streamSequence.set(this, void 0); _Conn_logger.set(this, void 0); _Conn_encoding.set(this, void 0); _Conn_transport.set(this, void 0); _Conn_internalUpstreamMap.set(this, void 0); _Conn_internalDownstreamMap.set(this, void 0); _Conn_metadataInternalDownstreamMap.set(this, void 0); _Conn_abortController.set(this, void 0); _Conn_wireConfig.set(this, void 0); _Conn_wire.set(this, void 0); _Conn_autoReconnect.set(this, void 0); _Conn_disconnectedEvent.set(this, void 0); _Conn_closedResolver.set(this, void 0); _Conn_connReconnectLock.set(this, void 0); _Conn_transportReconnectLock.set(this, void 0); _Conn_closeLock.set(this, void 0); _Conn_closeRequiredResolver.set(this, void 0); _Conn_downstreamReplyCallTransformStreamMap.set(this, void 0); _Conn_callEvent.set(this, void 0); _Conn_replyCallEvent.set(this, void 0); _Conn_reconnectingEvent.set(this, void 0); _Conn_reconnectedEvent.set(this, void 0); // from config __classPrivateFieldSet(this, _Conn_nodeId, config.nodeId, "f"); __classPrivateFieldSet(this, _Conn_protocolVersion, config.protocolVersion, "f"); __classPrivateFieldSet(this, _Conn_pingInterval, config.pingInterval, "f"); __classPrivateFieldSet(this, _Conn_pingTimeout, config.pingTimeout, "f"); __classPrivateFieldSet(this, _Conn_projectUuid, config.projectUuid, "f"); __classPrivateFieldSet(this, _Conn_tokenSource, config.tokenSource, "f"); // sequence __classPrivateFieldSet(this, _Conn_reqSequence, sequence_1.Sequence.forRequestId(), "f"); __classPrivateFieldSet(this, _Conn_streamSequence, sequence_1.Sequence.forStreamId(), "f"); __classPrivateFieldSet(this, _Conn_logger, new logger_1.LoggerConsole({ logLevel: config.logLevel ?? model_1.LOG_LEVEL.WARNING, }), "f"); __classPrivateFieldSet(this, _Conn_encoding, config.encoding, "f"); __classPrivateFieldSet(this, _Conn_transport, new transport_with_reconnect_1.TransportWithReconnect({ transportBuilder: async () => await config.connector.connect(config.address, config.negotiationParams), reconnectBaseIntervalMs: config.reconnectBaseInterval * 1e3, reconnectMaxIntervalMs: config.reconnectMaxInterval * 1e3, onReconnectRetryBefore: async ({ error }) => { __classPrivateFieldGet(this, _Conn_reconnectingEvent, "f").emit(new ReconnectingEvent({ error })); }, onReconnectSucceeded: async () => { await __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_createWire).call(this, asWireConfig(__classPrivateFieldGet(this, _Conn_wireConfig, "f"))); await __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_connect).call(this); }, }), "f"); __classPrivateFieldSet(this, _Conn_internalUpstreamMap, new Map(), "f"); __classPrivateFieldSet(this, _Conn_internalDownstreamMap, new Map(), "f"); __classPrivateFieldSet(this, _Conn_metadataInternalDownstreamMap, new Map(), "f"); __classPrivateFieldSet(this, _Conn_abortController, new AbortController(), "f"); __classPrivateFieldSet(this, _Conn_autoReconnect, config.autoReconnect, "f"); __classPrivateFieldSet(this, _Conn_disconnectedEvent, new typed_event_1.TypedEvent(), "f"); __classPrivateFieldSet(this, _Conn_closedResolver, new resolver_1.Resolver(), "f"); __classPrivateFieldSet(this, _Conn_connReconnectLock, new await_lock_1.default(), "f"); __classPrivateFieldSet(this, _Conn_transportReconnectLock, new await_lock_1.default(), "f"); __classPrivateFieldSet(this, _Conn_closeLock, new await_lock_1.default(), "f"); __classPrivateFieldSet(this, _Conn_closeRequiredResolver, new resolver_1.Resolver(), "f"); __classPrivateFieldSet(this, _Conn_downstreamReplyCallTransformStreamMap, new Map(), "f"); __classPrivateFieldSet(this, _Conn_callEvent, new typed_event_1.TypedEvent(), "f"); __classPrivateFieldSet(this, _Conn_replyCallEvent, new typed_event_1.TypedEvent(), "f"); __classPrivateFieldSet(this, _Conn_reconnectingEvent, new typed_event_1.TypedEvent(), "f"); __classPrivateFieldSet(this, _Conn_reconnectedEvent, new typed_event_1.TypedEvent(), "f"); } /** * ノードIDを取得します。 * @returns ノードID */ get nodeId() { return __classPrivateFieldGet(this, _Conn_nodeId, "f"); } /** * Ping間隔(秒)を取得します。 * @returns Ping間隔(秒) */ get pingInterval() { return __classPrivateFieldGet(this, _Conn_pingInterval, "f"); } /** * Pingタイムアウト(秒)を取得します。 * @returns Pingタイムアウト(秒) */ get pingTimeout() { return __classPrivateFieldGet(this, _Conn_pingTimeout, "f"); } /** * プロジェクトUUIDを取得します。 * @returns プロジェクトUUID */ get projectUuid() { return __classPrivateFieldGet(this, _Conn_projectUuid, "f"); } /** * アドレスを取得します。 * @returns アドレス */ get address() { return __classPrivateFieldGet(this, _Conn_transport, "f").address; } /** * エンコーディング名を取得します。 * @returns エンコーディング名 */ get encoding() { return __classPrivateFieldGet(this, _Conn_encoding, "f").name; } /** * トランスポート名を取得します。 * @returns トランスポート名 */ get transport() { return __classPrivateFieldGet(this, _Conn_transport, "f").name; } /** * アップストリームを開きます。 * @returns アップストリーム */ async openUpstream(config) { const expiryInterval = config.expiryInterval ?? Conn.DEFAULT_EXPIRY_INTERVAL; const qos = config.qos ?? Conn.DEFAULT_QOS; const ackInterval = config.ackInterval ?? Conn.DEFAULT_ACK_INTERVAL; const persist = config.persist ?? Conn.DEFAULT_PERSIST; const flushPolicy = config.flushPolicy ?? flush_policy_1.FlushPolicy.intervalOrBufferSize(); const closeTimeout = config.closeTimeout ?? Conn.DEFAULT_CLOSE_TIMEOUT; const closeSession = config.closeSession ?? Conn.DEFAULT_CLOSE_SESSION; if (!__classPrivateFieldGet(this, _Conn_wire, "f")) { throw new exceptions_2.ISCPException('wire is invalid.'); } const response = await __classPrivateFieldGet(this, _Conn_wire, "f").openUpstream(new message_1.UpstreamOpenRequest({ requestId: 0, sessionId: config.sessionId, expiryInterval, dataIds: config.dataIds ?? [], qos, ackInterval, extensionFields: new message_1.UpstreamOpenRequestExtensionFields({ persist }), })); if (response.resultCode !== message_1.RESULT_CODE.SUCCEEDED) { throw new exceptions_1.ISCPFailedMessageError(response); } const transformChunkAck = new web_streams_polyfill_1.TransformStream(); const transformReopen = new web_streams_polyfill_1.TransformStream(); const upstream = await upstream_1.Upstream.start({ logger: __classPrivateFieldGet(this, _Conn_logger, "f"), id: response.assignedStreamId, idAlias: response.assignedStreamIdAlias, sessionId: config.sessionId, dataIdAliases: response.dataIdAliases, serverTime: response.serverTime, closeTimeout, ackInterval, expiryInterval, qos, flushPolicy, persist, closeSession, resumeRequester: async (request) => { if (__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquired) { throw new exceptions_2.ISCPReconnectingError(); } return await asWire(__classPrivateFieldGet(this, _Conn_wire, "f")).resumeUpstream(request); }, closeRequester: async (request) => { if (__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquired) { throw new exceptions_2.ISCPReconnectingError(); } return await asWire(__classPrivateFieldGet(this, _Conn_wire, "f")).closeUpstream(request); }, chunkSender: async (message) => { if (__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquired) { throw new exceptions_2.ISCPReconnectingError(); } return await asWire(__classPrivateFieldGet(this, _Conn_wire, "f")).sendUpstreamChunk(message); }, chunkAckStreamReader: transformChunkAck.readable.getReader(), reopenStreamReader: transformReopen.readable.getReader(), }); const internalUpstream = new InternalUpstream({ chunkAckWriter: transformChunkAck.writable.getWriter(), reopenWriter: transformReopen.writable.getWriter(), close: upstream.close.bind(upstream), }); __classPrivateFieldGet(this, _Conn_internalUpstreamMap, "f").set(response.assignedStreamIdAlias, internalUpstream); upstream.waitClosed().then(() => { __classPrivateFieldGet(this, _Conn_internalUpstreamMap, "f").delete(response.assignedStreamIdAlias); }); return upstream; } /** * ダウンストリームを開きます。 * @returns ダウンストリーム */ async openDownstream(config) { const streamIdAlias = __classPrivateFieldGet(this, _Conn_streamSequence, "f").next(); const dataIdAliasSequence = sequence_1.Sequence.forDataIdAlias(); const qos = config.qos ?? Conn.DEFAULT_QOS; const expiryInterval = config.expiryInterval ?? Conn.DEFAULT_EXPIRY_INTERVAL; const ackInterval = config.ackInterval ?? Conn.DEFAULT_ACK_INTERVAL; const omitEmptyChunk = config.omitEmptyChunk ?? Conn.DEFAULT_OMIT_EMPTY_CHUNK; const dataIdAliases = (config.dataIds ?? []).reduce((prev, cur) => { const alias = dataIdAliasSequence.next(); return { ...prev, [alias]: cur }; }, {}); if (!__classPrivateFieldGet(this, _Conn_wire, "f")) { throw new exceptions_2.ISCPException('wire is invalid.'); } const response = await __classPrivateFieldGet(this, _Conn_wire, "f").openDownstream(new downstream_1.DownstreamOpenRequest({ requestId: 0, desiredStreamIdAlias: streamIdAlias, downstreamFilters: config.filters, expiryInterval, dataIdAliases, qos, omitEmptyChunk, extensionFields: new downstream_1.DownstreamOpenRequestExtensionFields(), })); if (response.resultCode !== message_1.RESULT_CODE.SUCCEEDED) { throw new exceptions_1.ISCPFailedMessageError(response); } const transformChunk = new web_streams_polyfill_1.TransformStream(); const transformChunkAckComplete = new web_streams_polyfill_1.TransformStream(); const transformMetadata = new web_streams_polyfill_1.TransformStream(); const transformReopen = new web_streams_polyfill_1.TransformStream(); const downstream = await downstream_2.Downstream.start({ logger: __classPrivateFieldGet(this, _Conn_logger, "f"), id: response.assignedStreamId, idAlias: streamIdAlias, serverTime: response.serverTime, qos, expiryInterval, filters: config.filters, dataIdAliases, dataIdAliasSequence, ackInterval, omitEmptyChunk, resumeRequester: async (request) => { if (__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquired) { throw new exceptions_2.ISCPReconnectingError(); } return await asWire(__classPrivateFieldGet(this, _Conn_wire, "f")).resumeDownstream(request); }, closeRequester: async (request) => { if (__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquired) { throw new exceptions_2.ISCPReconnectingError(); } return await asWire(__classPrivateFieldGet(this, _Conn_wire, "f")).closeDownstream(request); }, chunkAckSender: async (message) => { if (__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquired) { throw new exceptions_2.ISCPReconnectingError(); } return await asWire(__classPrivateFieldGet(this, _Conn_wire, "f")).sendDownstreamChunkAck(message); }, metadataAckSender: async (metadata) => { if (__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquired) { throw new exceptions_2.ISCPReconnectingError(); } return await asWire(__classPrivateFieldGet(this, _Conn_wire, "f")).sendDownstreamMetadataAck(metadata); }, chunkIterator: new stream_reader_iterator_1.StreamReaderIterator(transformChunk.readable.getReader()), chunkAckCompleteIterator: new stream_reader_iterator_1.StreamReaderIterator(transformChunkAckComplete.readable.getReader()), metadataIterator: new stream_reader_iterator_1.StreamReaderIterator(transformMetadata.readable.getReader()), reopenIterator: new stream_reader_iterator_1.StreamReaderIterator(transformReopen.readable.getReader()), }); const internalDownstream = new InternalDownstream({ chunkWriter: transformChunk.writable.getWriter(), chunkAckCompleteWriter: transformChunkAckComplete.writable.getWriter(), metadataWriter: transformMetadata.writable.getWriter(), reopenWriter: transformReopen.writable.getWriter(), close: downstream.close.bind(downstream), }); __classPrivateFieldGet(this, _Conn_internalDownstreamMap, "f").set(streamIdAlias, internalDownstream); const sourceNodeIds = [...new Set(config.filters.map(({ sourceNodeId }) => sourceNodeId))]; for (const sourceNodeId of sourceNodeIds) { let downstreamMap = __classPrivateFieldGet(this, _Conn_metadataInternalDownstreamMap, "f").get(sourceNodeId); if (!downstreamMap) { downstreamMap = new Map(); __classPrivateFieldGet(this, _Conn_metadataInternalDownstreamMap, "f").set(sourceNodeId, downstreamMap); } downstreamMap.set(streamIdAlias, internalDownstream); } downstream.waitClosed().then(() => { __classPrivateFieldGet(this, _Conn_internalDownstreamMap, "f").delete(streamIdAlias); for (const sourceNodeId of sourceNodeIds) { __classPrivateFieldGet(this, _Conn_metadataInternalDownstreamMap, "f").get(sourceNodeId)?.delete(streamIdAlias); } }); return downstream; } /** * E2Eコールを送信します。 * @param upstreamCall アップストリームコール。 * @returns コールID。 */ async sendCall(upstreamCall) { const wire = asWire(__classPrivateFieldGet(this, _Conn_wire, "f")); const callId = (0, uuid_1.randomUUIDv4)(); const response = await wire.sendUpstreamCall(new message_1.UpstreamCall({ callId, requestCallId: '', destinationNodeId: upstreamCall.destinationNodeId, name: upstreamCall.name, type: upstreamCall.type, payload: upstreamCall.payload, extensionFields: new message_1.UpstreamCallExtensionFields(), })); if (response.resultCode !== message_1.RESULT_CODE.SUCCEEDED) { throw new exceptions_1.ISCPFailedMessageError(response); } return callId; } /** * E2Eコールのリプライを送信します。 * @param replyCall アップストリームリプライコール。 * @returns コールID。 */ async sendReplyCall(replyCall) { const wire = asWire(__classPrivateFieldGet(this, _Conn_wire, "f")); const callId = (0, uuid_1.randomUUIDv4)(); const response = await wire.sendUpstreamCall(new message_1.UpstreamCall({ callId, requestCallId: replyCall.requestCallId, destinationNodeId: replyCall.destinationNodeId, name: replyCall.name, type: replyCall.type, payload: replyCall.payload, extensionFields: new message_1.UpstreamCallExtensionFields(), })); if (response.resultCode !== message_1.RESULT_CODE.SUCCEEDED) { throw new exceptions_1.ISCPFailedMessageError(response); } return callId; } /** * E2Eコールを送信し、リプライコールを受信するまで待ちます。 * @param upstreamCall アップストリームコール。 * @returns ダウンストリームリプライコール */ async sendCallAndWaitReplyCall(upstreamCall) { const wire = asWire(__classPrivateFieldGet(this, _Conn_wire, "f")); const callId = (0, uuid_1.randomUUIDv4)(); try { const transformStream = new web_streams_polyfill_1.TransformStream(); __classPrivateFieldGet(this, _Conn_downstreamReplyCallTransformStreamMap, "f").set(callId, transformStream); const response = await wire.sendUpstreamCall(new message_1.UpstreamCall({ callId, requestCallId: '', destinationNodeId: upstreamCall.destinationNodeId, name: upstreamCall.name, type: upstreamCall.type, payload: upstreamCall.payload, extensionFields: new message_1.UpstreamCallExtensionFields(), })); if (response.resultCode !== message_1.RESULT_CODE.SUCCEEDED) { throw new exceptions_1.ISCPFailedMessageError(response); } const readDownstreamReplyCall = await transformStream.readable.getReader().read(); if (readDownstreamReplyCall instanceof exceptions_2.ISCPTimeoutError) { throw readDownstreamReplyCall; } if (readDownstreamReplyCall.done) { throw new exceptions_2.ISCPException('Failed to read downstreamReplyCall'); } return readDownstreamReplyCall.value; } finally { __classPrivateFieldGet(this, _Conn_downstreamReplyCallTransformStreamMap, "f").delete(callId); } } /** * 基準時刻を送信します。 * @param baseTime 基準時刻。 * @param options 基準時刻を送信する際のオプションを指定します。 */ async sendBaseTime(baseTime, options) { await __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_sendMetadata).call(this, baseTime, { persist: options?.persist ?? Conn.DEFAULT_SEND_BASE_TIME_OPTIONS_PERSIST, }); } /** * コネクションを閉じます。 */ async close() { __classPrivateFieldGet(this, _Conn_closeRequiredResolver, "f").resolve(); await __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_close).call(this); } /** * コネクションが閉じるまで待機します。 */ async waitClosed() { await __classPrivateFieldGet(this, _Conn_closedResolver, "f").wait(); } addEventListener(name, listener, options) { switch (name) { case Conn.EVENT.CALL: options?.once ? __classPrivateFieldGet(this, _Conn_callEvent, "f").once(listener) : __classPrivateFieldGet(this, _Conn_callEvent, "f").on(listener); return; case Conn.EVENT.REPLY_CALL: options?.once ? __classPrivateFieldGet(this, _Conn_replyCallEvent, "f").once(listener) : __classPrivateFieldGet(this, _Conn_replyCallEvent, "f").on(listener); return; case Conn.EVENT.DISCONNECTED: options?.once ? __classPrivateFieldGet(this, _Conn_disconnectedEvent, "f").once(listener) : __classPrivateFieldGet(this, _Conn_disconnectedEvent, "f").on(listener); return; case Conn.EVENT.RECONNECTING: options?.once ? __classPrivateFieldGet(this, _Conn_reconnectingEvent, "f").once(listener) : __classPrivateFieldGet(this, _Conn_reconnectingEvent, "f").on(listener); return; case Conn.EVENT.RECONNECTED: options?.once ? __classPrivateFieldGet(this, _Conn_reconnectedEvent, "f").once(listener) : __classPrivateFieldGet(this, _Conn_reconnectedEvent, "f").on(listener); return; default: throw new exceptions_2.ISCPException('Unrecognized EventName.'); } } removeEventListener(name, listener) { switch (name) { case Conn.EVENT.CALL: __classPrivateFieldGet(this, _Conn_callEvent, "f").off(listener); return; case Conn.EVENT.REPLY_CALL: __classPrivateFieldGet(this, _Conn_replyCallEvent, "f").off(listener); return; case Conn.EVENT.DISCONNECTED: __classPrivateFieldGet(this, _Conn_disconnectedEvent, "f").off(listener); return; case Conn.EVENT.RECONNECTING: __classPrivateFieldGet(this, _Conn_reconnectingEvent, "f").off(listener); return; case Conn.EVENT.RECONNECTED: __classPrivateFieldGet(this, _Conn_reconnectedEvent, "f").off(listener); return; default: throw new exceptions_2.ISCPException('Unrecognized EventName.'); } } } exports.Conn = Conn; _Conn_nodeId = new WeakMap(), _Conn_protocolVersion = new WeakMap(), _Conn_pingInterval = new WeakMap(), _Conn_pingTimeout = new WeakMap(), _Conn_projectUuid = new WeakMap(), _Conn_tokenSource = new WeakMap(), _Conn_reqSequence = new WeakMap(), _Conn_streamSequence = new WeakMap(), _Conn_logger = new WeakMap(), _Conn_encoding = new WeakMap(), _Conn_transport = new WeakMap(), _Conn_internalUpstreamMap = new WeakMap(), _Conn_internalDownstreamMap = new WeakMap(), _Conn_metadataInternalDownstreamMap = new WeakMap(), _Conn_abortController = new WeakMap(), _Conn_wireConfig = new WeakMap(), _Conn_wire = new WeakMap(), _Conn_autoReconnect = new WeakMap(), _Conn_disconnectedEvent = new WeakMap(), _Conn_closedResolver = new WeakMap(), _Conn_connReconnectLock = new WeakMap(), _Conn_transportReconnectLock = new WeakMap(), _Conn_closeLock = new WeakMap(), _Conn_closeRequiredResolver = new WeakMap(), _Conn_downstreamReplyCallTransformStreamMap = new WeakMap(), _Conn_callEvent = new WeakMap(), _Conn_replyCallEvent = new WeakMap(), _Conn_reconnectingEvent = new WeakMap(), _Conn_reconnectedEvent = new WeakMap(), _Conn_instances = new WeakSet(), _Conn_run = async function _Conn_run() { await __classPrivateFieldGet(this, _Conn_transport, "f").open(); const messageIO = new message_io_1.MessageIO({ encoding: __classPrivateFieldGet(this, _Conn_encoding, "f"), reader: __classPrivateFieldGet(this, _Conn_transport, "f"), writer: __classPrivateFieldGet(this, _Conn_transport, "f"), logger: __classPrivateFieldGet(this, _Conn_logger, "f"), }); const unreliableTransport = __classPrivateFieldGet(this, _Conn_transport, "f").getUnreliable(); const unreliableMessageIO = unreliableTransport ? new message_io_1.MessageIO({ encoding: __classPrivateFieldGet(this, _Conn_encoding, "f"), reader: unreliableTransport, writer: unreliableTransport, logger: __classPrivateFieldGet(this, _Conn_logger, "f"), }) : undefined; __classPrivateFieldSet(this, _Conn_wireConfig, { requestSequence: __classPrivateFieldGet(this, _Conn_reqSequence, "f"), reader: messageIO.read.bind(messageIO), writer: messageIO.write.bind(messageIO), unreliableReader: unreliableMessageIO?.read?.bind(unreliableMessageIO), unreliableWriter: unreliableMessageIO?.write?.bind(unreliableMessageIO), pingInterval: __classPrivateFieldGet(this, _Conn_pingInterval, "f"), pingTimeout: __classPrivateFieldGet(this, _Conn_pingTimeout, "f"), logger: __classPrivateFieldGet(this, _Conn_logger, "f"), }, "f"); await __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_createWire).call(this, __classPrivateFieldGet(this, _Conn_wireConfig, "f")); await __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_connect).call(this); }, _Conn_createWire = async function _Conn_createWire(wireConfig) { const wire = new wire_1.Wire(wireConfig); __classPrivateFieldSet(this, _Conn_wire, wire, "f"); wire.onDownstreamChunk = __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_handleDownstreamChunk).bind(this); wire.onDownstreamMetadata = __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_handleDownstreamMetadata).bind(this); wire.onDownstreamChunkAckComplete = __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_handleDownstreamChunkAckComplete).bind(this); wire.onUpstreamChunkAck = __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_handleUpstreamChunkAck).bind(this); wire.onDownstreamCall = __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_handleDownstreamCall).bind(this); wire.onPingTimeout = async () => { const overwriteError = new exceptions_2.ISCPTimeoutError('ping timeout.'); __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_reconnect).call(this, overwriteError); }; wire.onDisconnect = async (message) => { if (message.resultCode === message_1.RESULT_CODE.PING_TIMEOUT) { const overwriteError = new exceptions_2.ISCPTimeoutError('ping timeout.'); __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_reconnect).call(this, overwriteError); return; } const overwriteError = new exceptions_2.ISCPTransportClosedError(`${message.resultString} [code=${message.resultCode}]`); __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_close).call(this, overwriteError); }; wire.onError = async () => { }; wire.start().catch((error) => { const overwriteError = error instanceof Error ? error : new Error(String(error)); __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_close).call(this, overwriteError); }); }, _Conn_connect = async function _Conn_connect() { if (!__classPrivateFieldGet(this, _Conn_wire, "f")) { throw new Error('invalid wire.'); } const response = await __classPrivateFieldGet(this, _Conn_wire, "f").connect(new message_1.ConnectRequest({ requestId: 0, nodeId: __classPrivateFieldGet(this, _Conn_nodeId, "f") ?? constant_1.DEFAULT_NODE_ID, protocolVersion: __classPrivateFieldGet(this, _Conn_protocolVersion, "f"), pingInterval: __classPrivateFieldGet(this, _Conn_pingInterval, "f"), pingTimeout: __classPrivateFieldGet(this, _Conn_pingTimeout, "f"), extensionFields: new message_1.ConnectRequestExtensionFields({ accessToken: __classPrivateFieldGet(this, _Conn_tokenSource, "f") ? await __classPrivateFieldGet(this, _Conn_tokenSource, "f").call(this) : constant_1.DEFAULT_TOKEN_SOURCE, intdash: new message_1.IntdashExtensionFields({ projectUuid: __classPrivateFieldGet(this, _Conn_projectUuid, "f") ?? constant_1.NIL_UUID, }), }), })); if (response.resultCode !== message_1.RESULT_CODE.SUCCEEDED) { throw new exceptions_1.ISCPFailedMessageError(response); } }, _Conn_reconnect = async function _Conn_reconnect(overwriteError) { if (__classPrivateFieldGet(this, _Conn_closedResolver, "f").isDone) { return; } if (!__classPrivateFieldGet(this, _Conn_autoReconnect, "f")) { await __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_close).call(this, overwriteError); return; } await __classPrivateFieldGet(this, _Conn_connReconnectLock, "f").acquireAsync(); try { // @memo // 初回のエラーはここでemitする // transport.reconnect 内部のリトライエラーは、transport.onReconnectBeforeRetryで通知される __classPrivateFieldGet(this, _Conn_reconnectingEvent, "f").emit({ error: overwriteError }); await asWire(__classPrivateFieldGet(this, _Conn_wire, "f")).cancel(); await __classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquireAsync(); await __classPrivateFieldGet(this, _Conn_transport, "f").reconnect(); __classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").release(); for (const upstream of __classPrivateFieldGet(this, _Conn_internalUpstreamMap, "f").values()) { await upstream.reopenWriter.write(); } for (const downstream of __classPrivateFieldGet(this, _Conn_internalDownstreamMap, "f").values()) { await downstream.reopenWriter.write(); } __classPrivateFieldGet(this, _Conn_reconnectedEvent, "f").emit(); } catch (error) { if (__classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").acquired) { __classPrivateFieldGet(this, _Conn_transportReconnectLock, "f").release(); } const newOverwriteError = error instanceof Error ? error : new Error(String(error)); await __classPrivateFieldGet(this, _Conn_instances, "m", _Conn_close).call(this, newOverwriteError); } finally { __classPrivateFieldGet(this, _Conn_connReconnectLock, "f").release(); } }, _Conn_handleUpstreamChunkAck = async function _Conn_handleUpstreamChunkAck(chunkAck) { if (!__classPrivateFieldGet(this, _Conn_closeRequiredResolver, "f").isDone) { await __classPrivateFieldGet(this, _Conn_internalUpstreamMap, "f").get(chunkAck.streamIdAlias)?.chunkAckWriter.write(chunkAck); } }, _Conn_handleDownstreamChunk = async function _Conn_handleDownstreamChunk(chunk) { if (!__classPrivateFieldGet(this, _Conn_closeRequiredResolver, "f").isDone) { await __classPrivateFieldGet(this, _Conn_internalDownstreamMap, "f").get(chunk.streamIdAlias)?.chunkWriter.write(chunk); } }, _Conn_handleDownstreamMetadata = async function _Conn_handleDownstreamMetadata(metadata) { if (!__classPrivateFieldGet(this, _Conn_closeRequiredResolver, "f").isDone) { const downstreams = [...(__classPrivateFieldGet(this, _Conn_metadataInternalDownstreamMap, "f").get(metadata.sourceNodeId)?.values() ?? [])]; for (const downstream of downstreams) { await downstream.metadataWriter.write(metadata); } } }, _Conn_handleDownstreamChunkAckComplete = async function _Conn_handleDownstreamChunkAckComplete(chunkAckComplete) { if (!__classPrivateFieldGet(this, _Conn_closeRequiredResolver, "f").isDone) { await __classPrivateFieldGet(this, _Conn_internalDownstreamMap, "f") .get(chunkAckComplete.streamIdAlias) ?.chunkAckCompleteWriter.write(chunkAckComplete); } }, _Conn_handleDownstreamCall = async function _Conn_handleDownstreamCall(downstreamCall) { if (!__classPrivateFieldGet(this, _Conn_closeRequiredResolver, "f").isDone) { if (downstreamCall.requestCallId === '') { const modelDownstreamCall = new model_1.DownstreamCall({ callId: downstreamCall.callId, sourceNodeId: downstreamCall.sourceNodeId, name: downstreamCall.name, type: downstreamCall.type, payload: downstreamCall.payload, }); __classPrivateFieldGet(this, _Conn_callEvent, "f").emit(modelDownstreamCall); return; } const modelDownstreamReplyCall = new model_1.DownstreamReplyCall({ requestCalId: downstreamCall.requestCallId, sourceNodeId: downstreamCall.sourceNodeId, name: downstreamCall.name, type: downstreamCall.type, payload: downstreamCall.payload, }); __classPrivateFieldGet(this, _Conn_replyCallEvent, "f").emit(modelDownstreamReplyCall); const transformStream = __classPrivateFieldGet(this, _Conn_downstreamReplyCallTransformStreamMap, "f").get(downstreamCall.requestCallId); if (transformStream) { const writer = transformStream.writable.getWriter(); await writer.write(modelDownstreamReplyCall); await writer.close(); } } }, _Conn_sendMetadata = async function _Conn_sendMetadata(metadata, options) { const wire = asWire(__classPrivateFieldGet(this, _Conn_wire, "f")); const response = await wire.upstreamMetadata(new message_1.UpstreamMetadata({ requestId: 0, metadata, extensionFields: new message_1.UpstreamMetadataExtensionFields({ persist: options.persist, }), })); if (response.resultCode !== message_1.RESULT_CODE.SUCCEEDED) { throw new exceptions_1.ISCPFailedMessageError(response); } }, _Conn_close = async function _Conn_close(overwriteError) { // async-lock // closed なら true なら抜ける await __classPrivateFieldGet(this, _Conn_closeLock, "f").acquireAsync(); if (__classPrivateFieldGet(this, _Conn_closedResolver, "f").isDone) { return; } let errorToThrow = overwriteError; try { for (const upstream of __classPrivateFieldGet(this, _Conn_internalUpstreamMap, "f").values()) { await upstream.dispose(); } for (const downstream of __classPrivateFieldGet(this, _Conn_internalDownstreamMap, "f").values()) { await downstream.dispose(); } await __classPrivateFieldGet(this, _Conn_wire, "f")?.disconnect(new message_1.Disconnect({ resultCode: message_1.RESULT_CODE.NORMAL_CLOSURE, resultString: 'NORMAL_CLOSURE', extensionFields: new message_1.DisconnectExtensionFields(), })); } catch (error) { __classPrivateFieldGet(this, _Conn_logger, "f").warn(constant_1.LOGGER_TAG.CONN, error); errorToThrow = error instanceof Error ? error : new Error(String(error)); } try { await __classPrivateFieldGet(this, _Conn_wire, "f")?.cancel(); __classPrivateFieldGet(this, _Conn_abortController, "f").abort(); await __classPrivateFieldGet(this, _Conn_transport, "f").close(); } catch (error) { __classPrivateFieldGet(this, _Conn_logger, "f").error(constant_1.LOGGER_TAG.CONN, error); errorToThrow = error instanceof Error ? error : new Error(String(error)); } finally { __classPrivateFieldGet(this, _Conn_disconnectedEvent, "f").emit(new DisconnectedEvent({ error: errorToThrow, })); __classPrivateFieldGet(this, _Conn_closedResolver, "f").resolve(); __classPrivateFieldGet(this, _Conn_closeLock, "f").release(); __classPrivateFieldGet(this, _Conn_callEvent, "f").dispose(); __classPrivateFieldGet(this, _Conn_replyCallEvent, "f").dispose(); __classPrivateFieldGet(this, _Conn_disconnectedEvent, "f").dispose(); __classPrivateFieldGet(this, _Conn_downstreamReplyCallTransformStreamMap, "f").clear(); } }; /** エンコーディング名のデフォルト値です。 */ Conn.DEFAULT_ENCODING_NAME = transport_1.ENCODING_NAME.PROTOBUF; /** Ping間隔のデフォルト値です(秒)。 */ Conn.DEFAULT_PING_INTERVAL = 10; /** Pingタイムアウトのデフォルト値です(秒)。 */ Conn.DEFAULT_PING_TIMEOUT = 1; /** 有効期限のデフォルト値です(秒)。 */ Conn.DEFAULT_EXPIRY_INTERVAL = 1; /** Ack返却間隔のデフォルト値です(秒)。 */ Conn.DEFAULT_ACK_INTERVAL = 1; /** QoSのデフォルト値です。 */ Conn.DEFAULT_QOS = common_1.QOS.UNRELIABLE; /** 空チャンク省略フラグのデフォルト値です。 */ Conn.DEFAULT_OMIT_EMPTY_CHUNK = false; /** 永続化するかどうかのデフォルト値です。 */ Conn.DEFAULT_PERSIST = false; /** クローズのタイムアウトのデフォルト値です(秒)。 */ Conn.DEFAULT_CLOSE_TIMEOUT = 1; /** アップストリームクローズ時にセッションをクローズするかどうかのデフォルト値です。 */ Conn.DEFAULT_CLOSE_SESSION = false; /** 自動で再接続するかのデフォルト値です。 */ Conn.DEFAULT_AUTO_RECONNECT = true; /** 自動で再接続する際の、リトライ間隔の初期値のデフォルト値です(秒)。 */ Conn.DEFAULT_RECONNECT_BASE_INTERVAL = 0.1; /** 自動で再接続する際の、リトライ間隔のデフォルト値です(秒)。 */ Conn.DEFAULT_RECONNECT_MAX_INTERVAL = 5; /** 基準時刻を送信する際に永続化するかどうかのデフォルト値です。 */ Conn.DEFAULT_SEND_BASE_TIME_OPTIONS_PERSIST = false; /** * @event イベント */ Conn.EVENT = { /** * E2Eコールを受信した時に呼び出されるイベントです。 */ CALL: 'call', /** * E2Eリプライコールを受信した時に呼び出されるイベントです。 */ REPLY_CALL: 'replyCall', /** * iSCPが切断された時に呼び出されるイベントです。 */ DISCONNECTED: 'disconnected', /** * iSCPの再接続が開始された時に呼び出されるイベントです。 */ RECONNECTING: 'reconnecting', /** * iSCPの再接続が成功した時に呼び出されるイベントです。 */ RECONNECTED: 'reconnected', }; // // Static Classes // /** * Connの中で使用するUpstreamクラス */ class InternalUpstream { constructor(init) { this.chunkAckWriter = init.chunkAckWriter; this.reopenWriter = init.reopenWriter; this.close = init.close; } async dispose() { await this.chunkAckWriter.close(); await this.reopenWriter.close(); await this.close(); } } /** * Connの中で使用するDownstreamクラス */ class InternalDownstream { constructor(init) { this.chunkWriter = init.chunkWriter; this.chunkAckCompleteWriter = init.chunkAckCompleteWriter; this.metadataWriter = init.metadataWriter; this.reopenWriter = init.reopenWriter; this.close = init.close; } async dispose() { await this.chunkWriter.close(); await this.chunkAckCompleteWriter.close(); await this.metadataWriter.close(); await this.reopenWriter.close(); await this.close(); } } // // Static functions // const toEncodingByName = (encodingName) => { switch (encodingName) { case transport_1.ENCODING_NAME.PROTOBUF: return new encoding_1.Protobuf(); case transport_1.ENCODING_NAME.JSON: return new encoding_1.Json(); default: throw new exceptions_1.ISCPUnexpectedError('Unrecognized encoding.'); } }; const asWireConfig = (wireConfig) => { if (wireConfig) { return wireConfig; } throw new Error('invalid wireConfig.'); }; const asWire = (wire) => { if (wire) { return wire; } throw new Error('invalid wire.'); }; //# sourceMappingURL=conn.js.map