ocpp-ws-io 2.1.4 → 2.1.6
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.
- package/README.md +6 -6
- package/dist/adapters/redis.d.mts +1 -1
- package/dist/adapters/redis.d.ts +1 -1
- package/dist/adapters/redis.js +2 -2
- package/dist/adapters/redis.js.map +1 -1
- package/dist/adapters/redis.mjs +2 -2
- package/dist/adapters/redis.mjs.map +1 -1
- package/dist/browser.d.mts +5 -0
- package/dist/browser.d.ts +5 -0
- package/dist/browser.js.map +1 -1
- package/dist/browser.mjs.map +1 -1
- package/dist/{index-CagcFzyZ.d.mts → index-1QBeqAuc.d.mts} +34 -2
- package/dist/{index-CagcFzyZ.d.ts → index-1QBeqAuc.d.ts} +34 -2
- package/dist/index.d.mts +26 -8
- package/dist/index.d.ts +26 -8
- package/dist/index.js +109 -19
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +108 -18
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/browser.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/browser/index.ts","../src/helpers/index.ts","../src/middleware.ts","../src/init-logger.ts","../src/browser/emitter.ts","../src/browser/errors.ts","../src/browser/queue.ts","../src/types.ts","../src/util.ts","../src/browser/util.ts","../src/browser/client.ts"],"sourcesContent":["// ─── Core ────────────────────────────────────────────────────────\n\nexport * from \"../helpers/index.js\";\nexport * from \"../middleware.js\";\nexport type { Validator, ValidatorSchema } from \"../validator.js\";\nexport { BrowserOCPPClient } from \"./client.js\";\n// ─── Errors ──────────────────────────────────────────────────────\nexport {\n type RPCError,\n RPCFormationViolationError,\n RPCFormatViolationError,\n RPCFrameworkError,\n RPCGenericError,\n RPCInternalError,\n RPCMessageTypeNotSupportedError,\n RPCNotImplementedError,\n RPCNotSupportedError,\n RPCOccurrenceConstraintViolationError,\n RPCPropertyConstraintViolationError,\n RPCProtocolError,\n RPCSecurityError,\n RPCTypeConstraintViolationError,\n TimeoutError,\n} from \"./errors.js\";\n// ─── Types ───────────────────────────────────────────────────────\nexport {\n type AllMethodNames,\n type AnyOCPPProtocol,\n type BrowserClientEvents,\n type BrowserClientOptions,\n type CallHandler,\n type CallOptions,\n type CloseOptions,\n ConnectionState,\n type HandlerContext,\n type LoggerLike,\n type LoggingConfig,\n MessageType,\n NOREPLY,\n type OCPPCall,\n type OCPPCallError,\n type OCPPCallResult,\n type OCPPMessage,\n type OCPPProtocol,\n type OCPPRequestType,\n type OCPPResponseType,\n type WildcardHandler,\n} from \"./types.js\";\n// ─── Utilities ───────────────────────────────────────────────────\nexport { createRPCError, getErrorPlainObject } from \"./util.js\";\n","import type {\n AuthAccept,\n AuthCallback,\n ConnectionMiddleware,\n LoggerLike,\n LoggingConfig,\n MiddlewareContext,\n MiddlewareFunction,\n} from \"../types.js\";\n\n// ─── Middleware Definition ───────────────────────────────────────\n\n/**\n * Utility to define and strongly-type a ConnectionMiddleware function.\n * This provides immediate IDE autocomplete for the `ConnectionContext`.\n */\nexport function defineMiddleware(\n mw: ConnectionMiddleware,\n): ConnectionMiddleware {\n return mw;\n}\n\n/**\n * Utility to define and strongly-type an RPC Middleware function.\n * This provides immediate IDE autocomplete for the `MiddlewareContext`\n * used when passing middleware to `client.use()`.\n */\nexport function defineRpcMiddleware<TContext = MiddlewareContext>(\n mw: MiddlewareFunction<TContext>,\n): MiddlewareFunction<TContext> {\n return mw;\n}\n\n// ─── Auth Definition & Composition ───────────────────────────────\n\n/**\n * Utility to define and strongly-type an AuthCallback function.\n * This provides immediate IDE autocomplete for the handshake and arguments.\n */\nexport function defineAuth<TSession = Record<string, unknown>>(\n cb: AuthCallback<TSession>,\n): AuthCallback<TSession> {\n return cb;\n}\n\n/**\n * Combines multiple AuthCallback functions sequentially.\n *\n * Flow matching standard middleware logic:\n * - If one callback `reject(err)` is called, the loop drops the connection instantly.\n * - If one callback `accept(opts)` is called, the loop terminates and grants the connection.\n * - If the loop finishes without anyone calling accept, it rejects with 401 Unauthorized.\n */\nexport function combineAuth(...cbs: AuthCallback[]): AuthCallback {\n return async (ctx) => {\n let accepted = false;\n let rejected = false;\n\n // Wrap the underlying accept/reject purely to detect when they fire\n const trackedAccept = (opts?: AuthAccept<any>) => {\n accepted = true;\n ctx.accept(opts);\n };\n\n const trackedReject = (code?: number, message?: string): never => {\n rejected = true;\n return ctx.reject(code, message);\n };\n\n const trackedCtx: import(\"../types.js\").AuthContext = {\n ...ctx,\n accept: trackedAccept,\n reject: trackedReject,\n };\n\n try {\n for (const cb of cbs) {\n if (ctx.signal.aborted || accepted || rejected) break;\n\n // Native callbacks from user might be sync or async\n const p = cb(trackedCtx);\n if (p instanceof Promise) {\n await p;\n }\n\n if (accepted || rejected) break;\n }\n\n // If loop finishes and nothing was explicitly decided, drop the connection\n if (!accepted && !rejected) {\n trackedReject(\n 401,\n \"Unauthorized (All composeAuth handlers passed without accepting)\",\n );\n }\n } catch (_err) {\n if (!rejected) {\n trackedReject(\n 500,\n \"Internal Server Error during auth compose execution\",\n );\n }\n }\n };\n}\n\n// ─── Logging Middleware ──────────────────────────────────────────\n\n/**\n * Creates a middleware that logs all RPC exchanges using the provided logger.\n * Logs start/end of calls and results with duration.\n */\nexport function createLoggingMiddleware(\n logger: LoggerLike,\n identity: string,\n config: LoggingConfig | boolean = {},\n): MiddlewareFunction<MiddlewareContext, any> {\n const options = typeof config === \"object\" ? config : {};\n const { exchangeLog = false, prettify = false } = options;\n\n return async (ctx, next) => {\n const start = Date.now();\n const method = ctx.method;\n\n // Use info if exchangeLog is enabled, otherwise debug\n const level = exchangeLog ? \"info\" : \"debug\";\n\n switch (ctx.type) {\n case \"incoming_call\":\n if (exchangeLog && prettify) {\n logger[level]?.(`⚡ ${identity} ← ${method} [IN]`, {\n messageId: ctx.messageId,\n method: ctx.method,\n protocol: ctx.protocol,\n payload: ctx.params,\n direction: \"IN\",\n });\n } else {\n logger[level]?.(`CALL ←`, {\n messageId: ctx.messageId,\n method: ctx.method,\n protocol: ctx.protocol,\n payload: ctx.params,\n direction: \"IN\",\n });\n }\n break;\n\n case \"outgoing_call\":\n if (exchangeLog && prettify) {\n logger[level]?.(`⚡ ${identity} → ${method} [OUT]`, {\n method: ctx.method,\n params: ctx.params,\n direction: \"OUT\",\n });\n } else {\n logger[level]?.(`CALL →`, {\n method: ctx.method,\n params: ctx.params,\n direction: \"OUT\",\n });\n }\n break;\n }\n\n try {\n const result = await next();\n const durationMs = Date.now() - start;\n\n switch (ctx.type) {\n case \"incoming_call\":\n if (result !== undefined && result !== null) {\n if (exchangeLog && prettify) {\n logger[level]?.(`✅ ${identity} → ${method} [RES]`, {\n messageId: ctx.messageId,\n method: ctx.method,\n durationMs,\n params: result,\n direction: \"OUT\",\n });\n } else {\n logger[level]?.(`CALLRESULT →`, {\n messageId: ctx.messageId,\n method: ctx.method,\n durationMs,\n params: result,\n direction: \"OUT\",\n });\n }\n }\n break;\n\n case \"outgoing_call\":\n if (exchangeLog && prettify) {\n logger[level]?.(`✅ ${identity} ← ${method} [RES]`, {\n messageId: (ctx as any).messageId,\n method: ctx.method,\n durationMs,\n payload: result,\n direction: \"IN\",\n });\n } else {\n logger[level]?.(`CALLRESULT ←`, {\n messageId: (ctx as any).messageId,\n method: ctx.method,\n durationMs,\n payload: result,\n direction: \"IN\",\n });\n }\n break;\n }\n\n return result;\n } catch (err) {\n const msg = (err as Error).message;\n const durationMs = Date.now() - start;\n\n if (ctx.type === \"incoming_call\") {\n if (exchangeLog && prettify) {\n logger.error?.(`🚨 ${identity} → ${method} [ERR]`, {\n messageId: ctx.messageId,\n method: ctx.method,\n durationMs,\n error: msg,\n direction: \"OUT\",\n });\n } else {\n logger.error?.(`CALLERROR →`, {\n messageId: ctx.messageId,\n method: ctx.method,\n durationMs,\n error: msg,\n direction: \"OUT\",\n });\n }\n } else if (ctx.type === \"outgoing_call\") {\n if (exchangeLog && prettify) {\n logger.warn?.(`🚨 ${identity} ← ${method} [ERR]`, {\n messageId: (ctx as any).messageId,\n method: ctx.method,\n durationMs,\n error: msg,\n direction: \"IN\",\n });\n } else {\n logger.warn?.(`CALLERROR ←`, {\n messageId: (ctx as any).messageId,\n method: ctx.method,\n durationMs,\n error: msg,\n direction: \"IN\",\n });\n }\n }\n throw err;\n }\n };\n}\n","/**\n * Middleware handling for intercepting and modifying OCPP operations.\n *\n * Implements an onion-model middleware stack (similar to Koa/Axios)\n * allowing cross-cutting concerns like logging, authentication, and validation.\n */\n\nexport type MiddlewareNext<TReturn = unknown> = () => Promise<TReturn>;\n\nexport type MiddlewareFunction<TContext, TReturn = unknown> = (\n context: TContext,\n next: MiddlewareNext<TReturn>,\n) => Promise<TReturn> | TReturn;\n\nexport class MiddlewareStack<TContext> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private _stack: MiddlewareFunction<TContext, any>[] = [];\n\n /**\n * Add a middleware function to the stack.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n use<TReturn = any>(middleware: MiddlewareFunction<TContext, TReturn>): void {\n this._stack.push(middleware);\n }\n\n /**\n * Execute the middleware stack composed with a runner function.\n *\n * @param context The context object to pass through middleware\n * @param runner The final function to execute (the \"core\" logic)\n */\n async execute<TReturn = unknown>(\n context: TContext,\n runner: (context: TContext) => Promise<TReturn> | TReturn,\n ): Promise<TReturn> {\n let index = -1;\n\n const dispatch = async (i: number): Promise<TReturn> => {\n if (i <= index) {\n throw new Error(\"next() called multiple times\");\n }\n index = i;\n\n const fn = this._stack[i];\n\n if (i === this._stack.length) {\n return runner(context);\n }\n\n if (!fn) {\n return undefined as unknown as TReturn;\n }\n\n return fn(context, () => dispatch(i + 1));\n };\n\n return dispatch(0);\n }\n}\n","/**\n * Internal utility to initialize a logger from LoggingConfig.\n *\n * - `undefined` → default voltlog-io with console transport\n * - `false` → null (logging disabled)\n * - `LoggingConfig` → custom handler or configured voltlog-io\n */\n\nimport {\n consoleTransport,\n createLogger,\n type LogEntry,\n type LogLevelName,\n type LogMiddleware,\n prettyTransport,\n} from \"voltlog-io\";\nimport type { LoggerLike, LoggingConfig } from \"./types.js\";\n\n// ─── Display middleware ─────────────────────────────────────────\n\n/**\n * Check if any display option differs from its default.\n */\nfunction hasDisplayCustomization(config: LoggingConfig): boolean {\n return (\n config.showMetadata === false ||\n config.showSourceMeta === false ||\n config.prettifySource === true ||\n config.prettifyMetadata === true\n );\n}\n\n/**\n * Build a voltlog-io LogMiddleware that transforms context/meta\n * before the transport sees them, so prettyTransport's colors are preserved.\n *\n * Strategy:\n * - hide → clear the field so prettyTransport skips it\n * - prettify → embed a readable string into `entry.message` and clear the raw field\n */\nfunction buildDisplayMiddleware(config: LoggingConfig): LogMiddleware {\n const showMeta = config.showMetadata ?? true;\n const showSource = config.showSourceMeta ?? true;\n const prettySrc = config.prettifySource ?? false;\n const prettyMeta = config.prettifyMetadata ?? false;\n\n // ANSI color codes for prettification\n const DIM = \"\\x1b[2;37m\"; // dim white\n const RESET = \"\\x1b[0m\"; // reset all styles\n const CYAN = \"\\x1b[36m\"; // cyan\n\n return (entry: LogEntry, next: (e: LogEntry) => void) => {\n // ── Source context ──\n if (!showSource) {\n // Hide entirely\n entry.context = undefined;\n } else if (prettySrc && entry.context) {\n // Build compact tag like [OCPPServer/WT159]\n const parts: string[] = [];\n if (entry.context.component) parts.push(String(entry.context.component));\n if (entry.context.identity) parts.push(String(entry.context.identity));\n if (parts.length > 0) {\n // Embed into message and clear context\n entry.message = `${DIM}[${parts.join(\"/\")}]${RESET} ${entry.message}`;\n entry.context = undefined;\n }\n }\n\n // ── Trailing metadata ──\n const meta = entry.meta as Record<string, unknown> | undefined;\n if (!showMeta) {\n // Hide entirely\n entry.meta = {} as typeof entry.meta;\n } else if (prettyMeta && meta && Object.keys(meta).length > 0) {\n // Build key=value pairs, embed into message, clear meta\n const pairs = Object.entries(meta)\n .filter(([, v]) => v !== undefined && v !== null)\n .map(([k, v]) => {\n let valStr = typeof v === \"object\" ? JSON.stringify(v) : String(v);\n // Apply some basic dimming for non-string values or objects to keep it clean\n if (typeof v === \"string\") {\n valStr = `${DIM}${valStr}${RESET}`;\n } else {\n valStr = `${DIM}${valStr}${RESET}`;\n }\n return `${CYAN}${k}${RESET}=${valStr}`;\n })\n .join(\" \");\n if (pairs) {\n entry.message = `${entry.message} ${pairs}`;\n }\n entry.meta = {} as typeof entry.meta;\n }\n\n next(entry);\n };\n}\n\n// ─── Public API ─────────────────────────────────────────────────\n\n/**\n * Resolve a LoggingConfig | false | undefined into a LoggerLike or null.\n */\nexport function initLogger(\n config: LoggingConfig | false | undefined,\n defaultContext?: Record<string, unknown>,\n): LoggerLike | null {\n // Explicitly disabled\n if (config === false) return null;\n if (config?.enabled === false) return null;\n\n // Custom external logger provided — use as-is\n if (config?.logger) {\n if (defaultContext && config.logger.child) {\n return config.logger.child(defaultContext);\n }\n return config.logger;\n }\n\n // Build default voltlog-io\n const level = (config?.level ?? \"INFO\") as LogLevelName;\n const usePrettify = config?.prettify ?? false;\n\n const transports = usePrettify\n ? [prettyTransport({ level })]\n : [consoleTransport({ level })];\n\n if (config?.handler) {\n const customTransport = config.handler;\n transports.push({\n name: \"customHandler\",\n write: (entry) => customTransport(entry),\n });\n }\n\n // Build display middleware if any display options are set\n const middleware: LogMiddleware[] = [];\n if (config && hasDisplayCustomization(config)) {\n middleware.push(buildDisplayMiddleware(config));\n }\n\n const logger = createLogger({\n level,\n transports,\n middleware: middleware.length > 0 ? middleware : undefined,\n });\n\n // Bind default context (e.g. identity)\n if (defaultContext && Object.keys(defaultContext).length > 0) {\n return logger.child(defaultContext);\n }\n\n return logger;\n}\n","/**\n * Tiny browser-compatible typed EventEmitter.\n * Drop-in replacement for Node.js EventEmitter in browser contexts.\n */\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Listener = (...args: any[]) => void;\n\nexport class EventEmitter {\n private _listeners = new Map<string, Listener[]>();\n\n on(event: string, listener: Listener): this {\n const arr = this._listeners.get(event);\n if (arr) {\n arr.push(listener);\n } else {\n this._listeners.set(event, [listener]);\n }\n return this;\n }\n\n once(event: string, listener: Listener): this {\n const wrapper: Listener = (...args) => {\n this.off(event, wrapper);\n listener(...args);\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (wrapper as any).__wrapped = listener;\n return this.on(event, wrapper);\n }\n\n off(event: string, listener: Listener): this {\n const arr = this._listeners.get(event);\n if (!arr) return this;\n const idx = arr.findIndex(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (fn) => fn === listener || (fn as any).__wrapped === listener,\n );\n if (idx !== -1) arr.splice(idx, 1);\n if (arr.length === 0) this._listeners.delete(event);\n return this;\n }\n\n emit(event: string, ...args: unknown[]): boolean {\n const arr = this._listeners.get(event);\n if (!arr || arr.length === 0) return false;\n for (const fn of [...arr]) {\n fn(...args);\n }\n return true;\n }\n\n addListener(event: string, listener: Listener): this {\n return this.on(event, listener);\n }\n\n removeListener(event: string, listener: Listener): this {\n return this.off(event, listener);\n }\n\n removeAllListeners(event?: string): this {\n if (event) {\n this._listeners.delete(event);\n } else {\n this._listeners.clear();\n }\n return this;\n }\n\n listenerCount(event: string): number {\n return this._listeners.get(event)?.length ?? 0;\n }\n}\n","// ─── Base Errors ─────────────────────────────────────────────────\n\nexport class TimeoutError extends Error {\n constructor(message = \"Operation timed out\") {\n super(message);\n this.name = \"TimeoutError\";\n }\n}\n\n// ─── RPC Error Base ──────────────────────────────────────────────\n\nexport interface RPCError extends Error {\n readonly rpcErrorCode: string;\n readonly rpcErrorMessage: string;\n readonly details: Record<string, unknown>;\n}\n\nexport class RPCGenericError extends Error implements RPCError {\n readonly rpcErrorCode: string = \"GenericError\";\n readonly rpcErrorMessage: string = \"\";\n readonly details: Record<string, unknown>;\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message);\n this.name = \"RPCGenericError\";\n this.details = details;\n }\n}\n\n// ─── Specific RPC Errors ─────────────────────────────────────────\n\nexport class RPCNotImplementedError extends RPCGenericError {\n override readonly rpcErrorCode = \"NotImplemented\";\n override readonly rpcErrorMessage = \"Requested method is not known\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCNotImplementedError\";\n }\n}\n\nexport class RPCNotSupportedError extends RPCGenericError {\n override readonly rpcErrorCode = \"NotSupported\";\n override readonly rpcErrorMessage =\n \"Requested method is recognised but not supported\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCNotSupportedError\";\n }\n}\n\nexport class RPCInternalError extends RPCGenericError {\n override readonly rpcErrorCode = \"InternalError\";\n override readonly rpcErrorMessage =\n \"An internal error occurred and the receiver was not able to process the requested action successfully\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCInternalError\";\n }\n}\n\nexport class RPCProtocolError extends RPCGenericError {\n override readonly rpcErrorCode = \"ProtocolError\";\n override readonly rpcErrorMessage = \"Payload for action is incomplete\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCProtocolError\";\n }\n}\n\nexport class RPCSecurityError extends RPCGenericError {\n override readonly rpcErrorCode = \"SecurityError\";\n override readonly rpcErrorMessage =\n \"During the processing of action a security issue occurred preventing receiver from completing the action successfully\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCSecurityError\";\n }\n}\n\nexport class RPCFormationViolationError extends RPCGenericError {\n override readonly rpcErrorCode = \"FormationViolation\";\n override readonly rpcErrorMessage =\n \"Payload for action is syntactically incorrect or not conform the PDU structure for action\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCFormationViolationError\";\n }\n}\n\nexport class RPCFormatViolationError extends RPCGenericError {\n override readonly rpcErrorCode = \"FormatViolation\";\n override readonly rpcErrorMessage =\n \"Payload is syntactically correct but at least one field contains an invalid value\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCFormatViolationError\";\n }\n}\n\nexport class RPCPropertyConstraintViolationError extends RPCGenericError {\n override readonly rpcErrorCode = \"PropertyConstraintViolation\";\n override readonly rpcErrorMessage =\n \"Payload is syntactically correct but at least one of the fields violates data type constraints\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCPropertyConstraintViolationError\";\n }\n}\n\nexport class RPCOccurrenceConstraintViolationError extends RPCGenericError {\n override readonly rpcErrorCode = \"OccurrenceConstraintViolation\";\n override readonly rpcErrorMessage =\n \"Payload for action is syntactically correct but at least one of the fields violates occurrence constraints\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCOccurrenceConstraintViolationError\";\n }\n}\n\nexport class RPCTypeConstraintViolationError extends RPCGenericError {\n override readonly rpcErrorCode = \"TypeConstraintViolation\";\n override readonly rpcErrorMessage =\n \"Payload for action is syntactically correct but at least one of the fields violates type constraints\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCTypeConstraintViolationError\";\n }\n}\n\nexport class RPCMessageTypeNotSupportedError extends RPCGenericError {\n override readonly rpcErrorCode = \"MessageTypeNotSupported\";\n override readonly rpcErrorMessage =\n \"A message with a Message Type Number received that is not supported by this implementation\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCMessageTypeNotSupportedError\";\n }\n}\n\nexport class RPCFrameworkError extends RPCGenericError {\n override readonly rpcErrorCode = \"RpcFrameworkError\";\n override readonly rpcErrorMessage =\n \"Content of the call is not a valid RPC request\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCFrameworkError\";\n }\n}\n","/**\n * A concurrency-limited async queue.\n * Enqueues async functions and executes them with a configurable concurrency limit.\n */\nexport class Queue {\n private _concurrency: number;\n private _running = 0;\n private _queue: Array<{\n fn: () => Promise<unknown>;\n resolve: (value: unknown) => void;\n reject: (reason: unknown) => void;\n }> = [];\n\n constructor(concurrency = 1) {\n this._concurrency = Math.max(1, concurrency);\n }\n\n get concurrency(): number {\n return this._concurrency;\n }\n\n get pending(): number {\n return this._queue.length;\n }\n\n get running(): number {\n return this._running;\n }\n\n get size(): number {\n return this._running + this._queue.length;\n }\n\n setConcurrency(concurrency: number): void {\n this._concurrency = Math.max(1, concurrency);\n this._drain();\n }\n\n push<T>(fn: () => Promise<T>): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n this._queue.push({\n fn: fn as () => Promise<unknown>,\n resolve: resolve as (value: unknown) => void,\n reject,\n });\n this._drain();\n });\n }\n\n private _drain(): void {\n while (this._running < this._concurrency && this._queue.length > 0) {\n const item = this._queue.shift();\n this._running++;\n\n item\n ?.fn()\n .then(item.resolve)\n .catch(item.reject)\n .finally(() => {\n this._running--;\n this._drain();\n });\n }\n }\n}\n","import type { EventEmitter } from \"node:events\";\nimport type { IncomingMessage } from \"node:http\";\nimport type { Duplex } from \"node:stream\";\nimport type { TLSSocket } from \"node:tls\";\nimport type { LogEntry } from \"voltlog-io\";\nimport type {\n AllMethodNames,\n OCPPMethodMap,\n OCPPProtocolKey,\n OCPPRequestType,\n OCPPResponseType,\n} from \"./generated/index.js\";\nimport type { Validator } from \"./validator.js\";\n\nexport type {\n AllMethodNames,\n OCPPMethodMap,\n OCPPProtocolKey,\n OCPPRequestType,\n OCPPResponseType,\n};\n\n// ─── Typed EventEmitter ──────────────────────────────────────────\n\n/**\n * Utility type that overlays typed `.on()`, `.off()`, `.emit()` etc.\n * on top of Node.js EventEmitter. This is the foundation for type-safe\n * event handling throughout the library.\n */\nexport type TypedEventEmitter<\n TEvents extends Record<keyof TEvents, unknown[]>,\n> = Omit<\n EventEmitter,\n | \"on\"\n | \"once\"\n | \"off\"\n | \"emit\"\n | \"removeListener\"\n | \"addListener\"\n | \"removeAllListeners\"\n> & {\n on<K extends keyof TEvents | (string & {})>(\n event: K,\n listener: K extends keyof TEvents\n ? (...args: TEvents[K]) => void\n : (...args: unknown[]) => void,\n ): TypedEventEmitter<TEvents>;\n once<K extends keyof TEvents | (string & {})>(\n event: K,\n listener: K extends keyof TEvents\n ? (...args: TEvents[K]) => void\n : (...args: unknown[]) => void,\n ): TypedEventEmitter<TEvents>;\n off<K extends keyof TEvents | (string & {})>(\n event: K,\n listener: K extends keyof TEvents\n ? (...args: TEvents[K]) => void\n : (...args: unknown[]) => void,\n ): TypedEventEmitter<TEvents>;\n emit<K extends keyof TEvents | (string & {})>(\n event: K,\n ...args: K extends keyof TEvents ? TEvents[K] : unknown[]\n ): boolean;\n addListener<K extends keyof TEvents | (string & {})>(\n event: K,\n listener: K extends keyof TEvents\n ? (...args: TEvents[K]) => void\n : (...args: unknown[]) => void,\n ): TypedEventEmitter<TEvents>;\n removeListener<K extends keyof TEvents | (string & {})>(\n event: K,\n listener: K extends keyof TEvents\n ? (...args: TEvents[K]) => void\n : (...args: unknown[]) => void,\n ): TypedEventEmitter<TEvents>;\n removeAllListeners<K extends keyof TEvents | (string & {})>(\n event?: K,\n ): TypedEventEmitter<TEvents>;\n};\n\n// ─── OCPP Protocol ───────────────────────────────────────────────\n\nexport type OCPPProtocol = OCPPProtocolKey;\nexport type AnyOCPPProtocol = OCPPProtocol | (string & {});\n\n// ─── Connection State ────────────────────────────────────────────\n\nexport const ConnectionState = {\n CONNECTING: 0,\n OPEN: 1,\n CLOSING: 2,\n CLOSED: 3,\n} as const;\n\nexport type ConnectionState =\n (typeof ConnectionState)[keyof typeof ConnectionState];\n\n// ─── Security Profiles (OCPP Spec) ──────────────────────────────\n\nexport enum SecurityProfile {\n /** No security — plain WS, no auth (dev/testing only) */\n NONE = 0,\n /** Profile 1: Basic Auth over unsecured WS (ws://) — password-based */\n BASIC_AUTH = 1,\n /** Profile 2: TLS + Basic Auth (wss://) — server cert + password */\n TLS_BASIC_AUTH = 2,\n /** Profile 3: Mutual TLS (wss://) — client + server certificates */\n TLS_CLIENT_CERT = 3,\n}\n\n// ─── Message Types ───────────────────────────────────────────────\n\nexport const MessageType = {\n CALL: 2,\n CALLRESULT: 3,\n CALLERROR: 4,\n} as const;\n\nexport type MessageType = (typeof MessageType)[keyof typeof MessageType];\n\n// ─── OCPP Message Tuples ─────────────────────────────────────────\n\nexport type OCPPCall<T = unknown> = [2, string, string, T];\nexport type OCPPCallResult<T = unknown> = [3, string, T];\nexport type OCPPCallError = [\n 4,\n string,\n string,\n string,\n Record<string, unknown>,\n];\nexport type OCPPMessage<T = unknown> =\n | OCPPCall<T>\n | OCPPCallResult<T>\n | OCPPCallError;\n\n// ─── TLS Options ─────────────────────────────────────────────────\n\nexport interface TLSOptions {\n /** Server/client certificate (PEM) */\n cert?: string | Buffer;\n /** Private key (PEM) */\n key?: string | Buffer;\n /** CA certificate(s) for verification */\n ca?: string | Buffer | Array<string | Buffer>;\n /** Reject unauthorized certs (default: true) */\n rejectUnauthorized?: boolean;\n /** Passphrase for encrypted private key */\n passphrase?: string;\n}\n\n// ─── Handler Types ───────────────────────────────────────────────\n\nexport interface HandlerContext<T = unknown> {\n /** Unique message ID */\n messageId: string;\n /** OCPP method name (e.g. \"BootNotification\") */\n method: string;\n /** Active OCPP protocol version (e.g. \"ocpp1.6\") */\n protocol: string | undefined;\n /** Request parameters */\n params: T;\n /** Abort signal */\n signal: AbortSignal;\n}\n\nexport type CallHandler<TParams = unknown, TResult = unknown> = (\n context: HandlerContext<TParams>,\n) => TResult | Promise<TResult>;\n\nexport type WildcardHandler = (\n method: string,\n context: HandlerContext,\n) => unknown | Promise<unknown>;\n\nexport interface RouterHandlerContext<T = unknown> extends HandlerContext<T> {\n /** The specific server client that issued the message. */\n client: import(\"./server-client.js\").OCPPServerClient;\n}\n\nexport type RouterWildcardHandler = (\n method: string,\n context: RouterHandlerContext,\n) => unknown | Promise<unknown>;\n\n// ─── Call Options ────────────────────────────────────────────────\n\nexport interface CallOptions {\n /** Timeout in milliseconds for this specific call */\n timeoutMs?: number;\n /** Abort signal */\n signal?: AbortSignal;\n /**\n * Max retry attempts on TimeoutError (default: 0 = no retry).\n * Uses Full Jitter exponential backoff between retries.\n */\n retries?: number;\n /** Base delay in ms for exponential backoff between retries (default: 1000) */\n retryDelayMs?: number;\n /** Max delay cap in ms to prevent unbounded backoff (default: 30000) */\n retryMaxDelayMs?: number;\n /**\n * Idempotency key for deduplication. If provided, this value is used\n * as the OCPP messageId instead of generating a new random one.\n * Consumers can use the same key to guarantee exactly-once semantics\n * when retrying calls across reconnections.\n */\n idempotencyKey?: string;\n}\n\n// ─── Close Options ───────────────────────────────────────────────\n\nexport interface CloseOptions {\n /** WebSocket close code (default: 1000) */\n code?: number;\n /** Close reason string */\n reason?: string;\n /** Wait for pending calls to complete before closing */\n awaitPending?: boolean;\n /** Force-close without waiting */\n force?: boolean;\n}\n\n// ─── Handshake Info ──────────────────────────────────────────────\n\nexport interface HandshakeInfo {\n /** Charging station identity (from URL path) */\n identity: string;\n /** Remote IP address */\n remoteAddress: string;\n /** Request headers */\n headers: Record<string, string | string[] | undefined>;\n /** Negotiated subprotocols */\n protocols: Set<string>;\n /** Full URL pathname including params */\n pathname: string;\n /** Extracted dynamic route parameters */\n params: Record<string, string>;\n /** URL query parameters */\n query: URLSearchParams;\n /** Original HTTP request */\n request: IncomingMessage;\n /** Password from Basic Auth (Profile 1 & 2) */\n password?: Buffer;\n /** Client certificate (Profile 3 — mTLS) */\n clientCertificate?: ReturnType<TLSSocket[\"getPeerCertificate\"]>;\n /** Active security profile */\n securityProfile: SecurityProfile;\n}\n\n// ─── Session Data ────────────────────────────────────────────────\n\nexport type SessionData<T = Record<string, any>> = T;\n\n// ─── Logger Interface ────────────────────────────────────────────\n\n/**\n * Minimal logger contract — compatible with `console`, `pino`, `voltlog-io`,\n * or any custom object with these methods.\n *\n * All methods are optional so `console` works as-is.\n */\nexport interface LoggerLike {\n debug?(message: string, meta?: Record<string, unknown>): void;\n info?(message: string, meta?: Record<string, unknown>): void;\n warn?(message: string, meta?: Record<string, unknown>): void;\n error?(message: string, meta?: Record<string, unknown>): void;\n child?(context: Record<string, unknown>): LoggerLike;\n}\n\n/**\n * Minimal logger contract — compatible with `console`, `pino`, `voltlog-io`,\n * or any custom object with these methods.\n *\n * All methods are optional so `console` works as-is.\n * this is only not optional for the logger used by the library\n */\nexport interface LoggerLikeNotOptional {\n debug(message: string, meta?: Record<string, unknown>): void;\n info(message: string, meta?: Record<string, unknown>): void;\n warn(message: string, meta?: Record<string, unknown>): void;\n error(message: string, meta?: Record<string, unknown>): void;\n child(context: Record<string, unknown>): LoggerLike;\n}\n\n/**\n * Logging configuration for OCPPClient and OCPPServer.\n *\n * @example Default (auto console logging)\n * ```ts\n * const client = new OCPPClient({ identity: 'CP-101', endpoint: '...' });\n * // → Logs to console via voltlog-io by default\n * ```\n *\n * @example Disable logging\n * ```ts\n * new OCPPClient({ identity: 'CP-101', endpoint: '...', logging: false });\n * ```\n *\n * @example Custom logger\n * ```ts\n * new OCPPClient({ identity: 'CP-101', endpoint: '...', logging: { handler: pino() } });\n * ```\n */\nexport interface LoggingConfig {\n /** Enable/disable logging (default: true) */\n enabled?: boolean;\n /**\n * Enable OCPP exchange logging (default: false).\n * Adds `direction: 'IN' | 'OUT'` to OCPP message logs.\n * When combined with `prettify`, renders styled exchange lines:\n * `⚡ CP-101 → BootNotification [IN]`\n */\n exchangeLog?: boolean;\n /**\n * Enable pretty-printed colored output (default: false).\n * Uses voltlog-io's prettyTransport with icons, colors, and timestamps.\n * Without this, logs are structured JSON.\n */\n prettify?: boolean;\n /** Log level for the default voltlog-io logger (default: 'INFO') */\n level?: string;\n /** Custom logger — replaces the default voltlog-io entirely */\n logger?: LoggerLike;\n /** Custom VoltLog transport function — receives formatted logs */\n handler?: (entry: LogEntry) => void | Promise<void>;\n\n // ─── Display Options (only apply to default voltlog-io logger) ──\n\n /**\n * Show trailing metadata object in log output (default: true).\n * `INFO Server listening {\"port\":5000,\"host\":\"0.0.0.0\"}`\n * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ← hidden when false\n */\n showMetadata?: boolean;\n /**\n * Show source context object in log output (default: true).\n * `INFO Server listening {\"component\":\"OCPPServer\"} {\"port\":5000}`\n * ^^^^^^^^^^^^^^^^^^^^^^^^ ← hidden when false\n */\n showSourceMeta?: boolean;\n /**\n * Prettify source context into a compact tag (default: false).\n * `{\"component\":\"OCPPServer\",\"identity\":\"CP-1\"}` → `[OCPPServer/CP-1]`\n */\n prettifySource?: boolean;\n /**\n * Prettify trailing metadata into readable key=value pairs (default: false).\n * `{\"port\":5000,\"host\":\"0.0.0.0\"}` → `port=5000 host=0.0.0.0`\n */\n prettifyMetadata?: boolean;\n}\n\n// ─── Client Options ──────────────────────────────────────────────\n\nexport interface ClientOptions {\n /** Unique identity for this client (charging station ID) */\n identity: string;\n /** WebSocket endpoint URL (ws:// or wss://) */\n endpoint: string;\n /** OCPP Security Profile (default: NONE) */\n securityProfile?: SecurityProfile;\n /** Password for Basic Auth (Profile 1 & 2) */\n password?: string | Buffer;\n /** TLS options (Profile 2 & 3) */\n tls?: TLSOptions;\n /** OCPP subprotocols to negotiate */\n protocols?: AnyOCPPProtocol[];\n /** Additional WebSocket headers */\n headers?: Record<string, string>;\n /** Additional query parameters */\n query?: Record<string, string>;\n /** Enable automatic reconnection (default: true) */\n reconnect?: boolean;\n /** Maximum reconnection attempts (default: Infinity) */\n maxReconnects?: number;\n /** Back-off base delay in ms (default: 1000) */\n backoffMin?: number;\n /** Back-off max delay in ms (default: 30000) */\n backoffMax?: number;\n /** Call timeout in ms (default: 30000) */\n callTimeoutMs?: number;\n /** Ping interval in ms (default: 30000, 0 to disable) */\n pingIntervalMs?: number;\n /** Defer pings if activity detected (default: false) */\n deferPingsOnActivity?: boolean;\n /**\n * Pong response timeout in ms. If no pong is received within this\n * window after a ping, the connection is considered dead and terminated.\n * (default: pingIntervalMs + 5000, 0 to disable)\n */\n pongTimeoutMs?: number;\n /** Maximum concurrent outbound calls (default: 1) */\n callConcurrency?: number;\n /** Enable strict mode validation (default: false) */\n strictMode?: boolean | OCPPProtocol[];\n /** If defined, restricts strict mode validation ONLY to these methods */\n strictModeMethods?: Array<AllMethodNames<OCPPProtocol>>;\n /** Custom validators for strict mode */\n strictModeValidators?: Validator[];\n /** Max number of bad messages before closing (default: Infinity) */\n maxBadMessages?: number;\n /** Include error details in responses (default: false) */\n respondWithDetailedErrors?: boolean;\n /**\n * Logging configuration.\n * - `undefined` / not set → default voltlog-io with console (logging enabled)\n * - `false` → logging disabled entirely\n * - `LoggingConfig` → custom configuration\n */\n logging?: LoggingConfig | false;\n /** Rate Limiting configuration (Token Bucket) */\n rateLimit?: RateLimitOptions;\n /**\n * If true, calls made while disconnected are queued in-memory\n * and flushed automatically on reconnect. (default: false)\n */\n offlineQueue?: boolean;\n /**\n * Maximum number of messages to queue while offline.\n * Oldest messages are dropped when exceeded. (default: 100)\n */\n offlineQueueMaxSize?: number;\n}\n\n// ─── Rate Limit Options ──────────────────────────────────────────\n\nexport interface RateLimitOptions {\n /** Maximum number of messages allowed within the window */\n limit: number;\n /** Window size in milliseconds */\n windowMs: number;\n /**\n * Action to take when rate limit is exceeded.\n * - 'disconnect': Terminate the socket immediately (hard enforce).\n * - 'ignore': Drop the message entirely, letting the client back-off and retry.\n * - Custom callback: Perform custom logging or logic when exceeded.\n * (default: 'ignore')\n */\n onLimitExceeded?:\n | \"disconnect\"\n | \"ignore\"\n | ((\n client: import(\"./server-client.js\").OCPPServerClient,\n rawData: unknown,\n ) => void | Promise<void>);\n /**\n * Specific limits applied purely to individual methods (e.g. Heartbeat, BootNotification).\n * Note: The method must be parsed from the raw JSON payload to apply this.\n */\n methods?: Record<string, { limit: number; windowMs: number }>;\n}\n\n// ─── Router Options ──────────────────────────────────────────────\n\nexport interface RouterConfig {\n /** Accepted OCPP subprotocols (e.g. [\"ocpp1.6\"]) */\n protocols?: AnyOCPPProtocol[];\n /** Call timeout in ms — overrides server default */\n callTimeoutMs?: number;\n /** Ping interval in ms — overrides server default */\n pingIntervalMs?: number;\n /** Defer pings if activity detected — overrides server default */\n deferPingsOnActivity?: boolean;\n /** Max concurrent outbound calls — overrides server default */\n callConcurrency?: number;\n /** Enable strict mode validation — overrides server default */\n strictMode?: boolean | OCPPProtocol[];\n /** If defined, restricts strict mode validation ONLY to these methods */\n strictModeMethods?: Array<AllMethodNames<OCPPProtocol>>;\n /** Rate Limiting configuration — overrides server default */\n rateLimit?: RateLimitOptions;\n}\n\nexport interface CORSOptions {\n /** Allowed IPv4, IPv6, or CIDR ranges (e.g. \"10.0.0.0/8\") */\n allowedIPs?: string[];\n /** Allowed Origin header values (e.g. \"https://dashboard.example.com\") */\n allowedOrigins?: string[];\n /** Allowed WebSocket protocol schemes */\n allowedSchemes?: (\"ws\" | \"wss\")[];\n}\n\n// ─── Server Options ──────────────────────────────────────────────\n\nexport interface ServerOptions {\n /** OCPP Security Profile (default: NONE) */\n securityProfile?: SecurityProfile;\n /** TLS options for HTTPS server (Profile 2 & 3) */\n tls?: TLSOptions;\n /** Accepted OCPP subprotocols */\n protocols?: AnyOCPPProtocol[];\n /** Call timeout in ms — inherited by server clients (default: 30000) */\n callTimeoutMs?: number;\n /** Ping interval in ms — inherited by server clients (default: 30000) */\n pingIntervalMs?: number;\n /** Defer pings if activity detected — inherited (default: false) */\n deferPingsOnActivity?: boolean;\n /** Max concurrent outbound calls — inherited (default: 1) */\n callConcurrency?: number;\n /** Enable strict mode — inherited (default: false) */\n strictMode?: boolean | OCPPProtocol[];\n /** If defined, restricts strict mode validation ONLY to these methods */\n strictModeMethods?: Array<AllMethodNames<OCPPProtocol>>;\n /** Custom validators — inherited */\n strictModeValidators?: Validator[];\n /** Rate Limiting configuration — inherited */\n rateLimit?: RateLimitOptions;\n /** Max bad messages — inherited (default: Infinity) */\n maxBadMessages?: number;\n /** Include error details in responses — inherited (default: false) */\n respondWithDetailedErrors?: boolean;\n /**\n * Session inactivity timeout in milliseconds before garbage collection.\n * (default: 7200000 / 2 hours)\n */\n sessionTtlMs?: number;\n /**\n * Maximum time (ms) to wait for the auth callback to resolve during\n * a WebSocket upgrade handshake. If the callback does not settle within\n * this window, the socket is destroyed and an `upgradeAborted` event\n * is emitted. Set to `0` to disable. (default: 30000)\n */\n handshakeTimeoutMs?: number;\n /**\n * Logging configuration — inherited by server clients.\n * - `undefined` / not set → default voltlog-io with console\n * - `false` → logging disabled\n * - `LoggingConfig` → custom configuration\n */\n logging?: LoggingConfig | false;\n /**\n * Connection-level rate limiting (per-IP) applied at the HTTP upgrade boundary,\n * before any auth, TLS or JSON parsing occurs — blocks DDoS connection floods in ~1µs.\n * - `limit`: Max upgrade requests per IP within `windowMs` (default: 20)\n * - `windowMs`: Sliding window in ms (default: 10000)\n */\n connectionRateLimit?: {\n limit: number;\n windowMs: number;\n };\n /**\n * Maximum number of inactive sessions to retain in the bounded LRU cache.\n * Prevents OOM under DDoS or reconnection storms with transient identities.\n * (default: 50000)\n */\n maxSessions?: number;\n /**\n * Enable the built-in HTTP health/metrics endpoint.\n * When enabled, non-upgrade HTTP requests to `/health` return a JSON health check,\n * and requests to `/metrics` return Prometheus-compatible text metrics.\n * (default: false)\n */\n healthEndpoint?: boolean;\n}\n\n// ─── Observability ─────────────────────────────────────────────────\n\nexport interface OCPPServerStats {\n /** Number of currently connected WebSockets */\n connectedClients: number;\n /** Number of active memory sessions */\n activeSessions: number;\n /** Process uptime in seconds */\n uptimeSeconds: number;\n /** Process Memory Usage (bytes) */\n memoryUsage: NodeJS.MemoryUsage;\n /** Process CPU Time (microseconds) */\n cpuUsage: NodeJS.CpuUsage;\n /** Process ID */\n pid: number;\n /** Low-level WebSocket Server metrics */\n webSockets?: {\n /** Total active clients managed by the underlying ws server */\n total: number;\n /** Current messages waiting to be flushed to network (bytes) */\n bufferedAmount: number;\n };\n}\n\n// ─── Listen Options ──────────────────────────────────────────────\n\nexport interface ListenOptions {\n /** Existing HTTP/HTTPS server to attach to */\n server?: import(\"node:http\").Server | import(\"node:https\").Server;\n /** Hostname to bind to */\n host?: string;\n /** Signal to abort the listen */\n signal?: AbortSignal;\n}\n\n// ─── Auth Callback ───────────────────────────────────────────────\n\nexport interface AuthAccept<TSession = Record<string, unknown>> {\n /** Subprotocol to use for this client */\n protocol?: string;\n /** Session data attached to the client */\n session?: TSession;\n}\n\nexport type AuthCallback<TSession = Record<string, unknown>> = (\n ctx: AuthContext<TSession>,\n) => void | Promise<void>;\n\nexport type RoutePattern = string | RegExp;\n\nexport interface AuthRoute {\n pattern: RoutePattern | null; // null represents the default fallback route\n handler: AuthCallback<any>;\n}\n\n// ─── Event Types ─────────────────────────────────────────────────\n\nexport interface ClientEvents {\n open: [{ response: IncomingMessage }];\n close: [{ code: number; reason: string }];\n disconnect: [{ code: number; reason: string }];\n error: [Error];\n connecting: [{ url: string }];\n reconnect: [{ attempt: number; delay: number }];\n message: [OCPPMessage];\n call: [OCPPCall];\n callResult: [OCPPCallResult];\n callError: [OCPPCallError];\n badMessage: [{ message: string; error: Error }];\n ping: [];\n pong: [];\n strictValidationFailure: [{ message: unknown; error: Error }];\n}\n\nimport type { OCPPServerClient } from \"./server-client.js\";\n\nexport interface ServerEvents {\n client: [OCPPServerClient];\n error: [Error];\n upgradeError: [{ error: Error; socket: Duplex }];\n upgradeAborted: [\n {\n identity: string;\n reason: string;\n socket: Duplex;\n request: IncomingMessage;\n },\n ];\n closing: [];\n close: [];\n // Native WebSocketServer events\n connection: [\n socket: import(\"ws\").WebSocket,\n request: import(\"node:http\").IncomingMessage,\n ];\n listening: [];\n headers: [headers: string[], request: import(\"node:http\").IncomingMessage];\n}\n\n// ─── Event Adapter Interface ─────────────────────────────────────\n\nexport interface EventAdapterInterface {\n publish(channel: string, data: unknown): Promise<void>;\n publishBatch?(messages: { channel: string; data: unknown }[]): Promise<void>;\n subscribe(channel: string, handler: (data: unknown) => void): Promise<void>;\n unsubscribe(channel: string): Promise<void>;\n disconnect(): Promise<void>;\n\n // Presence Registry (Optional)\n setPresence?(identity: string, nodeId: string, ttl: number): Promise<void>;\n getPresence?(identity: string): Promise<string | null>;\n getPresenceBatch?(identities: string[]): Promise<(string | null)[]>;\n removePresence?(identity: string): Promise<void>;\n /**\n * Batch set multiple presence entries in a single pipeline.\n * Reduces N network round-trips to 1 for bulk presence updates.\n */\n setPresenceBatch?(\n entries: { identity: string; nodeId: string; ttl?: number }[],\n ): Promise<void>;\n\n // Observability Pipeline (Optional)\n metrics?(): Promise<Record<string, unknown>>;\n}\n\n// ─── Symbols ─────────────────────────────────────────────────────\n\nexport const NOREPLY: unique symbol = Symbol(\"NOREPLY\");\n// ─── Middleware ──────────────────────────────────────────────────\n\nexport type MiddlewareContext =\n | {\n type: \"incoming_call\";\n messageId: string;\n method: string;\n params: unknown;\n protocol?: string;\n }\n | {\n type: \"outgoing_call\";\n messageId: string;\n method: string;\n params: unknown;\n options: CallOptions;\n }\n | {\n type: \"incoming_result\";\n messageId: string;\n payload: unknown;\n method: string; // Correlated method name\n }\n | {\n type: \"incoming_error\";\n messageId: string;\n error: OCPPCallError;\n method: string; // Correlated method name\n };\n\nexport type { MiddlewareFunction, MiddlewareNext } from \"./middleware.js\";\n\n// ─── Router Component Types ──────────────────────────────────────────\n\nexport interface BaseConnectionContext {\n /** The handshake info from the upgrading WebSocket request */\n handshake: HandshakeInfo;\n /** Modifiable record object suitable for passing data between middlewares (e.g. auth tokens) */\n state: Record<string, unknown>;\n /** Safely reject the WebSocket connection explicitly with an HTTP code and reason */\n reject: (code?: number, message?: string) => never;\n}\n\nexport interface ConnectionContext extends BaseConnectionContext {\n /** Triggers the next middleware in the execution chain, optionally merging a payload into ctx.state */\n next: (payload?: Record<string, unknown>) => Promise<void>;\n}\n\nexport interface AuthContext<TSession = Record<string, unknown>>\n extends BaseConnectionContext {\n /** The AbortSignal representing if the client abruptly closed the underlying socket */\n signal: AbortSignal;\n /** Grants the connection and optionally sets the negotiated protocol or session metadata */\n accept: (options?: AuthAccept<TSession>) => void;\n}\n\nexport type ConnectionMiddleware = (\n ctx: ConnectionContext,\n) => Promise<void> | void;\n","import type { RPCError } from \"./errors.js\";\nimport * as errors from \"./errors.js\";\nimport type { LoggerLikeNotOptional } from \"./types.js\";\n\n// ─── RPC Error Factory ──────────────────────────────────────────\n\n/**\n * Registry mapping OCPP-J RPC error code strings to their corresponding\n * error constructors. Organized by OCPP spec error category.\n */\nconst RPC_ERROR_REGISTRY = new Map<\n string,\n new (\n message?: string,\n details?: Record<string, unknown>,\n ) => RPCError\n>([\n // Generic / framework errors\n [\"GenericError\", errors.RPCGenericError],\n [\"RpcFrameworkError\", errors.RPCFrameworkError],\n [\"MessageTypeNotSupported\", errors.RPCMessageTypeNotSupportedError],\n\n // Action-level errors\n [\"NotImplemented\", errors.RPCNotImplementedError],\n [\"NotSupported\", errors.RPCNotSupportedError],\n [\"InternalError\", errors.RPCInternalError],\n\n // Protocol / security errors\n [\"ProtocolError\", errors.RPCProtocolError],\n [\"SecurityError\", errors.RPCSecurityError],\n\n // Payload validation errors\n [\"FormatViolation\", errors.RPCFormatViolationError],\n [\"FormationViolation\", errors.RPCFormationViolationError],\n [\"PropertyConstraintViolation\", errors.RPCPropertyConstraintViolationError],\n [\n \"OccurrenceConstraintViolation\",\n errors.RPCOccurrenceConstraintViolationError,\n ],\n [\"TypeConstraintViolation\", errors.RPCTypeConstraintViolationError],\n]);\n\n/**\n * Instantiate a typed RPCError from a string error code.\n * Returns an RPCGenericError if the code is not recognized.\n */\nexport function createRPCError(\n code: string,\n message?: string,\n details: Record<string, unknown> = {},\n): RPCError {\n const Ctor = RPC_ERROR_REGISTRY.get(code) ?? errors.RPCGenericError;\n return new Ctor(message, details);\n}\n\n// ─── Error Serialization ────────────────────────────────────────\n\n/**\n * Known error properties to extract, in a defined order.\n * This covers standard Error fields plus common OCPP RPC fields.\n */\nconst ERROR_PROPERTIES = [\n \"name\",\n \"message\",\n \"stack\",\n \"code\",\n \"rpcErrorCode\",\n \"rpcErrorMessage\",\n \"details\",\n] as const;\n\n/**\n * Convert an Error (or subclass) into a plain, JSON-safe object.\n *\n * Extracts well-known properties explicitly rather than relying on\n * Object.getOwnPropertyNames to avoid exposing internal fields and\n * to guarantee a stable output shape.\n *\n * If a property holds a non-serializable value (functions, symbols,\n * circular references), it is silently skipped.\n */\nexport function getErrorPlainObject(err: Error): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const prop of ERROR_PROPERTIES) {\n const value = (err as unknown as Record<string, unknown>)[prop];\n if (value !== undefined) {\n // Skip functions and symbols — they aren't JSON-serializable\n if (typeof value === \"function\" || typeof value === \"symbol\") continue;\n\n // Test serializability for complex values\n if (typeof value === \"object\" && value !== null) {\n try {\n JSON.stringify(value);\n result[prop] = value;\n } catch {\n // Skip non-serializable properties (circular refs, etc.)\n }\n } else {\n result[prop] = value;\n }\n }\n }\n\n // Ensure we always have at least name and message\n if (!result.name) result.name = err.name;\n if (!result.message) result.message = err.message;\n\n return result;\n}\n\n// ─── Package Identity ───────────────────────────────────────────\n\nconst PKG_NAME = \"ocpp-ws-io\";\nconst PKG_VERSION = \"1.0.1\";\n\n/**\n * Get the package identifier string used in HTTP headers and logging.\n * Format: `ocpp-ws-io/1.0.0`\n */\nexport function getPackageIdent(): string {\n return `${PKG_NAME}/${PKG_VERSION}`;\n}\n\n/* \n No-op logger for when logging is disabled.\n \n*/\nexport const NOOP_LOGGER: LoggerLikeNotOptional = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n child: () => NOOP_LOGGER,\n};\n","import type { RPCError } from \"./errors.js\";\nimport * as errors from \"./errors.js\";\n\nexport { NOOP_LOGGER } from \"../util.js\";\n\n// ─── RPC Error Factory ──────────────────────────────────────────\n\nconst RPC_ERROR_REGISTRY = new Map<\n string,\n new (\n message?: string,\n details?: Record<string, unknown>,\n ) => RPCError\n>([\n [\"GenericError\", errors.RPCGenericError],\n [\"RpcFrameworkError\", errors.RPCFrameworkError],\n [\"MessageTypeNotSupported\", errors.RPCMessageTypeNotSupportedError],\n [\"NotImplemented\", errors.RPCNotImplementedError],\n [\"NotSupported\", errors.RPCNotSupportedError],\n [\"InternalError\", errors.RPCInternalError],\n [\"ProtocolError\", errors.RPCProtocolError],\n [\"SecurityError\", errors.RPCSecurityError],\n [\"FormatViolation\", errors.RPCFormatViolationError],\n [\"FormationViolation\", errors.RPCFormationViolationError],\n [\"PropertyConstraintViolation\", errors.RPCPropertyConstraintViolationError],\n [\n \"OccurrenceConstraintViolation\",\n errors.RPCOccurrenceConstraintViolationError,\n ],\n [\"TypeConstraintViolation\", errors.RPCTypeConstraintViolationError],\n]);\n\n/**\n * Instantiate a typed RPCError from a string error code.\n * Returns an RPCGenericError if the code is not recognized.\n */\nexport function createRPCError(\n code: string,\n message?: string,\n details: Record<string, unknown> = {},\n): RPCError {\n const Ctor = RPC_ERROR_REGISTRY.get(code) ?? errors.RPCGenericError;\n return new Ctor(message, details);\n}\n\n// ─── Error Serialization ────────────────────────────────────────\n\nconst ERROR_PROPERTIES = [\n \"name\",\n \"message\",\n \"stack\",\n \"code\",\n \"rpcErrorCode\",\n \"rpcErrorMessage\",\n \"details\",\n] as const;\n\n/**\n * Convert an Error into a plain, JSON-safe object.\n */\nexport function getErrorPlainObject(err: Error): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const prop of ERROR_PROPERTIES) {\n const value = (err as unknown as Record<string, unknown>)[prop];\n if (value !== undefined) {\n if (typeof value === \"function\" || typeof value === \"symbol\") continue;\n\n if (typeof value === \"object\" && value !== null) {\n try {\n JSON.stringify(value);\n result[prop] = value;\n } catch {\n // Skip non-serializable\n }\n } else {\n result[prop] = value;\n }\n }\n }\n\n if (!result.name) result.name = err.name;\n if (!result.message) result.message = err.message;\n\n return result;\n}\n","/// <reference lib=\"dom\" />\n\n/**\n * BrowserOCPPClient — A full-featured browser WebSocket RPC client for OCPP.\n *\n * Feature-complete port of OCPPClient for browser environments:\n * - Typed event emitter (no Node.js EventEmitter dependency)\n * - Auto-reconnection with exponential backoff + jitter\n * - Concurrency-limited call queue\n * - Version-specific & wildcard handlers\n * - Abort signal support\n * - Bad message handling\n * - NOREPLY support\n */\nimport { initLogger } from \"../init-logger.js\";\nimport { type MiddlewareFunction, MiddlewareStack } from \"../middleware.js\";\nimport type { MiddlewareContext } from \"../types.js\";\nimport { EventEmitter } from \"./emitter.js\";\nimport {\n type RPCError,\n RPCGenericError,\n RPCMessageTypeNotSupportedError,\n TimeoutError,\n} from \"./errors.js\";\nimport { Queue } from \"./queue.js\";\nimport {\n type AllMethodNames,\n type BrowserClientOptions,\n type CallHandler,\n type CallOptions,\n type CloseOptions,\n ConnectionState,\n type HandlerContext,\n type LoggerLike,\n type LoggerLikeNotOptional,\n MessageType,\n NOREPLY,\n type OCPPCall,\n type OCPPCallError,\n type OCPPCallResult,\n type OCPPMessage,\n type OCPPProtocol,\n type OCPPRequestType,\n type OCPPResponseType,\n type WildcardHandler,\n} from \"./types.js\";\nimport { createRPCError, getErrorPlainObject, NOOP_LOGGER } from \"./util.js\";\n\nconst { CONNECTING, OPEN, CLOSING, CLOSED } = ConnectionState;\n\ninterface PendingCall {\n resolve: (value: unknown) => void;\n reject: (reason: unknown) => void;\n timeoutHandle: ReturnType<typeof setTimeout>;\n abortHandler?: () => void;\n method: string;\n sentAt: number;\n}\n\n/**\n * BrowserOCPPClient — A typed WebSocket RPC client for OCPP in browser environments.\n *\n * API-compatible with `OCPPClient` from `ocpp-ws-io`, adapted for the browser\n * WebSocket API (no Node.js dependencies).\n *\n * @example\n * ```ts\n * import { BrowserOCPPClient } from \"ocpp-ws-io/browser\";\n *\n * const client = new BrowserOCPPClient({\n * identity: \"CP001\",\n * endpoint: \"wss://central.example.com/ocpp\",\n * protocols: [\"ocpp1.6\"],\n * });\n *\n * client.on(\"open\", () => console.log(\"Connected!\"));\n * await client.connect();\n * ```\n */\nexport class BrowserOCPPClient<\n P extends OCPPProtocol = OCPPProtocol,\n> extends EventEmitter {\n // Static connection states\n static readonly CONNECTING = CONNECTING;\n static readonly OPEN = OPEN;\n static readonly CLOSING = CLOSING;\n static readonly CLOSED = CLOSED;\n\n private _options: Required<\n Pick<\n BrowserClientOptions,\n | \"identity\"\n | \"endpoint\"\n | \"callTimeoutMs\"\n | \"callConcurrency\"\n | \"maxBadMessages\"\n | \"respondWithDetailedErrors\"\n | \"reconnect\"\n | \"maxReconnects\"\n | \"backoffMin\"\n | \"backoffMax\"\n >\n > &\n BrowserClientOptions;\n\n private _state: (typeof ConnectionState)[keyof typeof ConnectionState] =\n CLOSED;\n private _ws: WebSocket | null = null;\n private _protocol: string | undefined;\n private _identity: string;\n\n private _handlers = new Map<string, CallHandler>();\n private _wildcardHandler: WildcardHandler | null = null;\n private _pendingCalls = new Map<string, PendingCall>();\n private _pendingResponses = new Set<string>();\n private _callQueue: Queue;\n private _closePromise: Promise<{ code: number; reason: string }> | null =\n null;\n private _reconnectAttempt = 0;\n private _reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private _badMessageCount = 0;\n private _outboundBuffer: string[] = [];\n private _logger: LoggerLike;\n private _middleware: MiddlewareStack<MiddlewareContext>;\n\n constructor(options: BrowserClientOptions) {\n super();\n\n if (!options.identity) {\n throw new Error(\"identity is required\");\n }\n\n this._identity = options.identity;\n\n this._options = {\n reconnect: true,\n maxReconnects: Infinity,\n backoffMin: 1000,\n backoffMax: 30000,\n callTimeoutMs: 30000,\n callConcurrency: 1,\n maxBadMessages: Infinity,\n respondWithDetailedErrors: false,\n ...options,\n };\n\n this._callQueue = new Queue(this._options.callConcurrency);\n this._middleware = new MiddlewareStack<MiddlewareContext>();\n\n // Initialize logger\n const loggerInstance = initLogger(this._options.logging, {\n component: \"BrowserOCPPClient\",\n identity: this._identity,\n });\n this._logger = loggerInstance || NOOP_LOGGER;\n }\n\n // ─── Getters ─────────────────────────────────────────────────\n\n get log(): LoggerLikeNotOptional {\n return this._logger as LoggerLikeNotOptional;\n }\n get identity(): string {\n return this._identity;\n }\n get protocol(): string | undefined {\n return this._protocol;\n }\n get state(): (typeof ConnectionState)[keyof typeof ConnectionState] {\n return this._state;\n }\n\n // ─── Connect ─────────────────────────────────────────────────\n\n async connect(): Promise<void> {\n if (this._state !== CLOSED) {\n throw new Error(`Cannot connect: client is in state ${this._state}`);\n }\n\n this._state = CONNECTING;\n this._reconnectAttempt = 0;\n\n return this._connectInternal();\n }\n\n private async _connectInternal(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const endpoint = this._buildEndpoint();\n\n this._logger.debug?.(\"Connecting\", { url: endpoint });\n this.emit(\"connecting\", { url: endpoint });\n\n let ws: WebSocket;\n try {\n ws = this._options.protocols?.length\n ? new WebSocket(endpoint, this._options.protocols)\n : new WebSocket(endpoint);\n } catch (err) {\n this._state = CLOSED;\n reject(err);\n return;\n }\n this._ws = ws;\n\n const onOpen = (event: Event) => {\n cleanup();\n this._state = OPEN;\n this._protocol = ws.protocol || undefined;\n this._badMessageCount = 0;\n\n // Narrow protocols to negotiated protocol for future reconnects\n if (ws.protocol && this._reconnectAttempt === 0) {\n this._options.protocols = [ws.protocol];\n }\n\n this._attachWebsocket(ws);\n\n // Flush outbound buffer (messages queued during CONNECTING)\n if (this._outboundBuffer.length > 0) {\n const buffer = this._outboundBuffer;\n this._outboundBuffer = [];\n for (const msg of buffer) this._ws?.send(msg);\n }\n\n this._logger.info?.(\"Connected\", {\n protocol: ws.protocol || undefined,\n });\n this.emit(\"open\", event);\n resolve();\n };\n\n const onError = (event: Event) => {\n cleanup();\n this._state = CLOSED;\n this._logger.error?.(\"Connection error\");\n this.emit(\"error\", event);\n reject(event);\n };\n\n const onClose = () => {\n cleanup();\n if (this._state === CONNECTING) {\n this._state = CLOSED;\n reject(new Error(\"WebSocket closed during connection\"));\n }\n };\n\n const cleanup = () => {\n ws.removeEventListener(\"open\", onOpen);\n ws.removeEventListener(\"error\", onError);\n ws.removeEventListener(\"close\", onClose);\n };\n\n ws.addEventListener(\"open\", onOpen);\n ws.addEventListener(\"error\", onError);\n ws.addEventListener(\"close\", onClose);\n });\n }\n\n // ─── Close ───────────────────────────────────────────────────\n\n async close(\n options: CloseOptions = {},\n ): Promise<{ code: number; reason: string }> {\n const {\n code = 1000,\n reason = \"\",\n awaitPending = true,\n force = false,\n } = options;\n\n if (this._closePromise) return this._closePromise;\n\n if (this._state === CLOSED) {\n return { code: 1000, reason: \"\" };\n }\n\n // Cancel reconnection\n if (this._reconnectTimer) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = null;\n }\n\n this._closePromise = this._closeInternal(code, reason, awaitPending, force);\n return this._closePromise;\n }\n\n private async _closeInternal(\n code: number,\n reason: string,\n awaitPending: boolean,\n force: boolean,\n ): Promise<{ code: number; reason: string }> {\n this._state = CLOSING;\n\n if (!force && awaitPending) {\n const pendingPromises = Array.from(this._pendingCalls.values()).map(\n (p) =>\n new Promise<void>((resolve) => {\n const origResolve = p.resolve;\n const origReject = p.reject;\n p.resolve = (v: unknown) => {\n origResolve(v);\n resolve();\n };\n p.reject = (r: unknown) => {\n origReject(r);\n resolve();\n };\n }),\n );\n if (pendingPromises.length > 0) {\n await Promise.allSettled(pendingPromises);\n }\n }\n\n return new Promise<{ code: number; reason: string }>((resolve) => {\n if (!this._ws || this._ws.readyState === WebSocket.CLOSED) {\n this._state = CLOSED;\n this._cleanup();\n const result = { code, reason };\n this.emit(\"close\", result);\n resolve(result);\n return;\n }\n\n const onClose = (event: CloseEvent) => {\n this._ws?.removeEventListener(\"close\", onClose);\n this._state = CLOSED;\n this._cleanup();\n const result = { code: event.code, reason: event.reason };\n this.emit(\"close\", result);\n resolve(result);\n };\n\n this._ws.addEventListener(\"close\", onClose);\n\n if (force) {\n // Browser WebSocket has no terminate(), close immediately\n this._ws.close();\n } else {\n // Validate close code (RFC 6455 §7.4)\n const validCode =\n code >= 1000 && code <= 4999 && ![1004, 1005, 1006].includes(code);\n this._ws.close(validCode ? code : 1000, reason);\n }\n });\n }\n\n // ─── Handlers ────────────────────────────────────────────────\n\n /**\n * Register a version-specific handler — `handle(\"ocpp1.6\", \"BootNotification\", handler)`.\n * This handler is only invoked when the active protocol matches the given version.\n */\n handle<V extends OCPPProtocol, M extends AllMethodNames<V>>(\n version: V,\n method: M,\n handler: (\n context: HandlerContext<OCPPRequestType<V, M>>,\n ) => OCPPResponseType<V, M> | Promise<OCPPResponseType<V, M>>,\n ): void;\n\n /**\n * Register a handler for the client's default protocol — `handle(\"BootNotification\", handler)`.\n * Uses the default protocol type parameter `P`.\n */\n handle<M extends AllMethodNames<P>>(\n method: M,\n handler: (\n context: HandlerContext<OCPPRequestType<P, M>>,\n ) => OCPPResponseType<P, M> | Promise<OCPPResponseType<P, M>>,\n ): void;\n\n /** Register a handler for a custom/extension method not in the typed OCPP method maps. */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n handle(\n method: string,\n handler: (context: HandlerContext<Record<string, any>>) => any,\n ): void;\n\n /** Register a wildcard handler for all unhandled methods. */\n handle(handler: WildcardHandler): void;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n handle(...args: any[]): void {\n if (args.length === 1 && typeof args[0] === \"function\") {\n this._wildcardHandler = args[0] as WildcardHandler;\n } else if (\n args.length === 2 &&\n typeof args[0] === \"string\" &&\n typeof args[1] === \"function\"\n ) {\n this._handlers.set(args[0], args[1] as CallHandler);\n } else if (\n args.length === 3 &&\n typeof args[0] === \"string\" &&\n typeof args[1] === \"string\" &&\n typeof args[2] === \"function\"\n ) {\n this._handlers.set(`${args[0]}:${args[1]}`, args[2] as CallHandler);\n } else {\n throw new Error(\n \"Invalid arguments: provide (version, method, handler), (method, handler), or (wildcardHandler)\",\n );\n }\n }\n\n removeHandler(method?: string): void;\n removeHandler(version: OCPPProtocol, method: string): void;\n removeHandler(versionOrMethod?: string, method?: string): void {\n if (versionOrMethod && method) {\n this._handlers.delete(`${versionOrMethod}:${method}`);\n } else if (versionOrMethod) {\n this._handlers.delete(versionOrMethod);\n } else {\n this._wildcardHandler = null;\n }\n }\n\n removeAllHandlers(): void {\n this._handlers.clear();\n this._wildcardHandler = null;\n }\n\n // ─── Middleware ──────────────────────────────────────────────\n\n /**\n * Register a middleware function to intercept calls and results.\n * Middleware executes in the order registered.\n */\n use(middleware: MiddlewareFunction<MiddlewareContext>): void {\n this._middleware.use(middleware);\n }\n\n // ─── Call ────────────────────────────────────────────────────\n\n /**\n * Call a version-specific typed method — `call(\"ocpp1.6\", \"BootNotification\", {...})`.\n * Provides full type inference for params and response based on the OCPP version.\n */\n async call<V extends OCPPProtocol, M extends AllMethodNames<V>>(\n version: V,\n method: M,\n params: OCPPRequestType<V, M>,\n options?: CallOptions,\n ): Promise<OCPPResponseType<V, M>>;\n\n /** Call a known typed method using the client's default protocol. */\n async call<M extends AllMethodNames<P>>(\n method: M,\n params: OCPPRequestType<P, M>,\n options?: CallOptions,\n ): Promise<OCPPResponseType<P, M>>;\n\n /** Call a known typed method with explicit response type. */\n async call<TResult = unknown>(\n method: string,\n params?: Record<string, unknown>,\n options?: CallOptions,\n ): Promise<TResult>;\n\n async call(...args: unknown[]): Promise<unknown> {\n let method: string;\n let params: unknown;\n let options: CallOptions;\n\n if (\n args.length >= 3 &&\n typeof args[0] === \"string\" &&\n typeof args[1] === \"string\"\n ) {\n // call(version, method, params, options?)\n method = args[1] as string;\n params = args[2] ?? {};\n options = (args[3] as CallOptions) ?? {};\n } else {\n // call(method, params?, options?)\n method = args[0] as string;\n params = args[1] ?? {};\n options = (args[2] as CallOptions) ?? {};\n }\n\n if (this._state !== OPEN) {\n throw new Error(`Cannot call: client is in state ${this._state}`);\n }\n\n return this._callQueue.push(() => this._sendCall(method, params, options));\n }\n\n private async _sendCall(\n method: string,\n params: unknown,\n options: CallOptions,\n ): Promise<unknown> {\n const msgId = this._generateMessageId();\n const timeoutMs = options.timeoutMs ?? this._options.callTimeoutMs;\n\n const ctx: MiddlewareContext = {\n type: \"outgoing_call\",\n messageId: msgId,\n method,\n params,\n options,\n };\n\n let callResult: unknown;\n\n await this._middleware.execute(ctx, async (c) => {\n const ctxvals = c as Extract<\n MiddlewareContext,\n { type: \"outgoing_call\" }\n >;\n\n const message: OCPPCall = [\n MessageType.CALL,\n msgId,\n ctxvals.method,\n ctxvals.params,\n ];\n const messageStr = JSON.stringify(message);\n\n callResult = await new Promise<unknown>((resolve, reject) => {\n const timeoutHandle = setTimeout(() => {\n this._pendingCalls.delete(msgId);\n this._logger.warn?.(\"Call timed out\", {\n messageId: msgId,\n method: ctxvals.method,\n timeoutMs,\n });\n reject(\n new TimeoutError(\n `Call to \"${ctxvals.method}\" timed out after ${timeoutMs}ms`,\n ),\n );\n }, timeoutMs);\n\n const pending: PendingCall = {\n resolve: resolve as (v: unknown) => void,\n reject,\n timeoutHandle,\n method: ctxvals.method,\n sentAt: Date.now(),\n };\n\n // Abort signal support\n if (options.signal) {\n if (options.signal.aborted) {\n clearTimeout(timeoutHandle);\n reject(options.signal.reason ?? new Error(\"Aborted\"));\n return;\n }\n const abortHandler = () => {\n clearTimeout(timeoutHandle);\n this._pendingCalls.delete(msgId);\n reject(options.signal?.reason ?? new Error(\"Aborted\"));\n };\n options.signal.addEventListener(\"abort\", abortHandler, {\n once: true,\n });\n pending.abortHandler = abortHandler;\n }\n\n this._pendingCalls.set(msgId, pending);\n this._ws?.send(messageStr);\n this.emit(\"message\", message);\n this.emit(\"call\", message);\n });\n });\n\n return callResult;\n }\n\n /**\n * Send a raw string message over the WebSocket (use with caution).\n * Messages sent while CONNECTING are buffered and flushed on open.\n */\n sendRaw(message: string): void {\n if (this._state === OPEN && this._ws) {\n this._ws.send(message);\n } else if (this._state === CONNECTING) {\n this._outboundBuffer.push(message);\n } else {\n throw new Error(\"Cannot send: client is not connected\");\n }\n }\n\n // ─── Reconfigure ─────────────────────────────────────────────\n\n reconfigure(options: Partial<BrowserClientOptions>): void {\n Object.assign(this._options, options);\n\n if (options.callConcurrency !== undefined) {\n this._callQueue.setConcurrency(options.callConcurrency);\n }\n }\n\n // ─── Internal: WebSocket attachment ──────────────────────────\n\n private _attachWebsocket(ws: WebSocket): void {\n ws.addEventListener(\"message\", (event: MessageEvent) =>\n this._onMessage(event.data),\n );\n ws.addEventListener(\"close\", (event: CloseEvent) =>\n this._onClose(event.code, event.reason),\n );\n ws.addEventListener(\"error\", (event: Event) => this.emit(\"error\", event));\n }\n\n // ─── Internal: Message handling ──────────────────────────────\n\n private _onMessage(data: unknown): void {\n const raw = typeof data === \"string\" ? data : String(data);\n\n let message: OCPPMessage;\n try {\n message = JSON.parse(raw) as OCPPMessage;\n if (!Array.isArray(message)) throw new Error(\"Message is not an array\");\n } catch (err) {\n this._onBadMessage(raw, err as Error);\n return;\n }\n\n const messageType = message[0];\n\n switch (messageType) {\n case MessageType.CALL:\n this._handleIncomingCall(message as OCPPCall);\n break;\n case MessageType.CALLRESULT:\n this._handleCallResult(message as OCPPCallResult);\n break;\n case MessageType.CALLERROR:\n this._handleCallError(message as OCPPCallError);\n break;\n default:\n this._onBadMessage(\n JSON.stringify(message),\n new RPCMessageTypeNotSupportedError(\n `Unknown message type: ${messageType}`,\n ),\n );\n }\n }\n\n private async _handleIncomingCall(message: OCPPCall): Promise<void> {\n const [, msgId, method, params] = message;\n\n const ctx: MiddlewareContext = {\n type: \"incoming_call\",\n messageId: msgId,\n method,\n params,\n protocol: this._protocol,\n };\n\n await this._middleware.execute(ctx, async (c) => {\n const ctxvals = c as Extract<\n MiddlewareContext,\n { type: \"incoming_call\" }\n >;\n\n const modifiedMessage: OCPPCall = [\n MessageType.CALL,\n ctxvals.messageId,\n ctxvals.method,\n ctxvals.params,\n ];\n this.emit(\"call\", modifiedMessage);\n\n if (this._state !== OPEN) {\n return;\n }\n\n try {\n if (this._pendingResponses.has(ctxvals.messageId)) {\n throw createRPCError(\n \"RpcFrameworkError\",\n `Already processing call with ID: ${ctxvals.messageId}`,\n );\n }\n\n const specificHandler =\n (this._protocol\n ? this._handlers.get(`${this._protocol}:${ctxvals.method}`)\n : undefined) ?? this._handlers.get(ctxvals.method);\n\n if (!specificHandler && !this._wildcardHandler) {\n throw createRPCError(\n \"NotImplemented\",\n `No handler for method: ${ctxvals.method}`,\n );\n }\n\n this._pendingResponses.add(ctxvals.messageId);\n\n const ac = new AbortController();\n const context: HandlerContext = {\n messageId: ctxvals.messageId,\n method: ctxvals.method,\n protocol: this._protocol,\n params: ctxvals.params,\n signal: ac.signal,\n };\n\n let result: unknown;\n if (specificHandler) {\n result = await specificHandler(context);\n } else if (this._wildcardHandler) {\n result = await this._wildcardHandler(ctxvals.method, context);\n }\n\n this._pendingResponses.delete(ctxvals.messageId);\n\n if (result === NOREPLY) return;\n\n const response: OCPPCallResult = [\n MessageType.CALLRESULT,\n ctxvals.messageId,\n result,\n ];\n this._ws?.send(JSON.stringify(response));\n this.emit(\"callResult\", response);\n } catch (err) {\n this._pendingResponses.delete(ctxvals.messageId);\n this._logger.error?.(\"Handler error\", {\n messageId: ctxvals.messageId,\n method: ctxvals.method,\n error: (err as Error).message,\n });\n\n const rpcErr =\n err instanceof RPCGenericError || (err as RPCError).rpcErrorCode\n ? (err as RPCError)\n : createRPCError(\"InternalError\", (err as Error).message);\n\n const details = this._options.respondWithDetailedErrors\n ? getErrorPlainObject(err as Error)\n : {};\n\n const errorResponse: OCPPCallError = [\n MessageType.CALLERROR,\n ctxvals.messageId,\n rpcErr.rpcErrorCode,\n rpcErr.rpcErrorMessage || (err as Error).message || \"\",\n details,\n ];\n this._ws?.send(JSON.stringify(errorResponse));\n this.emit(\"callError\", errorResponse);\n }\n });\n }\n\n private async _handleCallResult(message: OCPPCallResult): Promise<void> {\n const [, msgId, result] = message;\n\n if (!this._pendingCalls.has(msgId)) {\n this._logger.warn?.(\"Received CallResult for unknown messageId\", {\n messageId: msgId,\n });\n return;\n }\n\n const pending = this._pendingCalls.get(msgId)!;\n\n const ctx: MiddlewareContext = {\n type: \"incoming_result\",\n messageId: msgId,\n method: pending.method,\n payload: result,\n };\n\n await this._middleware.execute(ctx, async (c) => {\n const ctxvals = c as Extract<\n MiddlewareContext,\n { type: \"incoming_result\" }\n >;\n\n const modifiedMessage: OCPPCallResult = [\n MessageType.CALLRESULT,\n msgId,\n ctxvals.payload,\n ];\n this.emit(\"callResult\", modifiedMessage);\n\n clearTimeout(pending.timeoutHandle);\n this._pendingCalls.delete(msgId);\n pending.resolve(ctxvals.payload);\n });\n }\n\n private async _handleCallError(message: OCPPCallError): Promise<void> {\n const [, msgId, errorCode, errorMessage, errorDetails] = message;\n\n if (!this._pendingCalls.has(msgId)) {\n this._logger.warn?.(\"Received CallError for unknown messageId\", {\n messageId: msgId,\n });\n return;\n }\n\n const pending = this._pendingCalls.get(msgId)!;\n\n const error = createRPCError(errorCode, errorMessage, errorDetails);\n\n const ctx: MiddlewareContext = {\n type: \"incoming_error\",\n messageId: msgId,\n method: pending.method,\n error: error as unknown as OCPPCallError, // Map to types.ts expected `error` shape which takes OCPPCallError specifically here, though we pass it via RPCError\n };\n\n await this._middleware.execute(ctx, async (c) => {\n const ctxvals = c as Extract<\n MiddlewareContext,\n { type: \"incoming_error\" }\n >;\n\n // Cast back to any to extract dynamic properties cleanly\n const resolvedRpcErr = ctxvals.error as unknown as any;\n\n const modifiedMessage: OCPPCallError = [\n MessageType.CALLERROR,\n msgId,\n resolvedRpcErr.rpcErrorCode,\n resolvedRpcErr.message,\n resolvedRpcErr.rpcErrorDetails ?? {},\n ];\n this.emit(\"callError\", modifiedMessage);\n\n clearTimeout(pending.timeoutHandle);\n this._pendingCalls.delete(msgId);\n pending.reject(resolvedRpcErr);\n });\n }\n\n // ─── Internal: Bad message handling ──────────────────────────\n\n private _onBadMessage(rawMessage: string, error: Error): void {\n this._badMessageCount++;\n this._logger?.warn?.(\"Bad message\", {\n error: error.message,\n count: this._badMessageCount,\n });\n this.emit(\"badMessage\", { message: rawMessage, error });\n\n // Best-effort: try to extract messageId and respond with CALLERROR\n const match = rawMessage.match(/^\\s*\\[\\s*2\\s*,\\s*\"([^\"]+)\"/);\n if (match?.[1] && this._ws) {\n const errorResponse: OCPPCallError = [\n MessageType.CALLERROR,\n match[1],\n \"FormatViolation\",\n error.message || \"Invalid message format\",\n {},\n ];\n this._ws.send(JSON.stringify(errorResponse));\n this.emit(\"callError\", errorResponse);\n }\n\n if (this._badMessageCount >= this._options.maxBadMessages) {\n this.close({ code: 1002, reason: \"Too many bad messages\" }).catch(\n () => {},\n );\n }\n }\n\n // ─── Internal: Close handling ────────────────────────────────\n\n /**\n * Reject all in-flight calls and clear pending state.\n */\n private _rejectPendingCalls(reason: string): void {\n for (const [, pending] of this._pendingCalls) {\n clearTimeout(pending.timeoutHandle);\n pending.reject(new Error(reason));\n }\n this._pendingCalls.clear();\n this._pendingResponses.clear();\n }\n\n private _onClose(code: number, reason: string): void {\n this._rejectPendingCalls(`Connection closed (${code}: ${reason})`);\n\n if (this._state !== CLOSING) {\n // Unexpected close — emit disconnect (transient, reconnect may follow)\n this._logger?.info?.(\"Disconnected\", { code, reason });\n this.emit(\"disconnect\", { code, reason });\n\n if (\n this._options.reconnect &&\n this._reconnectAttempt < this._options.maxReconnects\n ) {\n this._scheduleReconnect();\n } else {\n // No reconnect — permanent close\n this._state = CLOSED;\n this.emit(\"close\", { code, reason });\n }\n } else {\n this._state = CLOSED;\n // close() handles the emit\n }\n }\n\n // ─── Internal: Reconnection ──────────────────────────────────\n\n /** Errors that should stop reconnection immediately */\n private static readonly _INTOLERABLE_ERRORS = new Set([\n \"Maximum redirects exceeded\",\n \"Server sent no subprotocol\",\n \"Server sent an invalid subprotocol\",\n \"Server sent a subprotocol but none was requested\",\n \"Invalid Sec-WebSocket-Accept header\",\n ]);\n\n private _scheduleReconnect(): void {\n this._reconnectAttempt++;\n this._state = CONNECTING;\n\n // Exponential backoff with jitter (OCPP 2.0.1 §J.1)\n const base = this._options.backoffMin;\n const max = this._options.backoffMax;\n const delayMs = Math.min(\n max,\n base * 2 ** (this._reconnectAttempt - 1) * (0.5 + Math.random() * 0.5),\n );\n\n this._logger?.warn?.(\"Reconnecting\", {\n attempt: this._reconnectAttempt,\n delayMs: Math.round(delayMs),\n });\n this.emit(\"reconnect\", { attempt: this._reconnectAttempt, delay: delayMs });\n\n this._reconnectTimer = setTimeout(async () => {\n this._reconnectTimer = null;\n try {\n await this._connectInternal();\n } catch (err) {\n // Intolerable errors — do not retry\n const msg = err instanceof Error ? err.message : \"\";\n if (BrowserOCPPClient._INTOLERABLE_ERRORS.has(msg)) {\n this._logger?.error?.(\"Intolerable error — stopping reconnection\", {\n error: msg,\n });\n this._state = CLOSED;\n this.emit(\"close\", { code: 1001, reason: msg });\n return;\n }\n\n if (\n this._reconnectAttempt < this._options.maxReconnects &&\n this._options.reconnect\n ) {\n this._scheduleReconnect();\n } else {\n // Max reconnects exhausted\n this._state = CLOSED;\n this.emit(\"close\", {\n code: 1001,\n reason: \"Max reconnection attempts exhausted\",\n });\n }\n }\n }, delayMs);\n }\n\n // ─── Internal: Endpoint building ─────────────────────────────\n\n private _buildEndpoint(): string {\n let url = this._options.endpoint;\n\n if (!url.endsWith(\"/\")) url += \"/\";\n url += encodeURIComponent(this._identity);\n\n if (this._options.query) {\n const params = new URLSearchParams(this._options.query);\n url += (url.includes(\"?\") ? \"&\" : \"?\") + params.toString();\n }\n\n return url;\n }\n\n // ─── Internal: Cleanup ───────────────────────────────────────\n\n private _cleanup(): void {\n this._closePromise = null;\n this._ws = null;\n }\n\n // ─── Internal: ID Generation ─────────────────────────────────\n\n private _generateMessageId(): string {\n // 1. Try native crypto.randomUUID (Fastest, secure, requires HTTPS/localhost)\n if (\n typeof crypto !== \"undefined\" &&\n typeof crypto.randomUUID === \"function\"\n ) {\n return crypto.randomUUID();\n }\n\n // 2. Fallback to Math.random() for older browsers or insecure HTTP contexts\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/browser/index.ts","../src/helpers/index.ts","../src/middleware.ts","../src/init-logger.ts","../src/browser/emitter.ts","../src/browser/errors.ts","../src/browser/queue.ts","../src/types.ts","../src/util.ts","../src/browser/util.ts","../src/browser/client.ts"],"sourcesContent":["// ─── Core ────────────────────────────────────────────────────────\n\nexport * from \"../helpers/index.js\";\nexport * from \"../middleware.js\";\nexport type { Validator, ValidatorSchema } from \"../validator.js\";\nexport { BrowserOCPPClient } from \"./client.js\";\n// ─── Errors ──────────────────────────────────────────────────────\nexport {\n type RPCError,\n RPCFormationViolationError,\n RPCFormatViolationError,\n RPCFrameworkError,\n RPCGenericError,\n RPCInternalError,\n RPCMessageTypeNotSupportedError,\n RPCNotImplementedError,\n RPCNotSupportedError,\n RPCOccurrenceConstraintViolationError,\n RPCPropertyConstraintViolationError,\n RPCProtocolError,\n RPCSecurityError,\n RPCTypeConstraintViolationError,\n TimeoutError,\n} from \"./errors.js\";\n// ─── Types ───────────────────────────────────────────────────────\nexport {\n type AllMethodNames,\n type AnyOCPPProtocol,\n type BrowserClientEvents,\n type BrowserClientOptions,\n type CallHandler,\n type CallOptions,\n type CloseOptions,\n ConnectionState,\n type HandlerContext,\n type LoggerLike,\n type LoggingConfig,\n MessageType,\n NOREPLY,\n type OCPPCall,\n type OCPPCallError,\n type OCPPCallResult,\n type OCPPMessage,\n type OCPPProtocol,\n type OCPPRequestType,\n type OCPPResponseType,\n type WildcardHandler,\n} from \"./types.js\";\n// ─── Utilities ───────────────────────────────────────────────────\nexport { createRPCError, getErrorPlainObject } from \"./util.js\";\n","import type {\n AuthAccept,\n AuthCallback,\n ConnectionMiddleware,\n LoggerLike,\n LoggingConfig,\n MiddlewareContext,\n MiddlewareFunction,\n} from \"../types.js\";\n\n// ─── Middleware Definition ───────────────────────────────────────\n\n/**\n * Utility to define and strongly-type a ConnectionMiddleware function.\n * This provides immediate IDE autocomplete for the `ConnectionContext`.\n */\nexport function defineMiddleware(\n mw: ConnectionMiddleware,\n): ConnectionMiddleware {\n return mw;\n}\n\n/**\n * Utility to define and strongly-type an RPC Middleware function.\n * This provides immediate IDE autocomplete for the `MiddlewareContext`\n * used when passing middleware to `client.use()`.\n */\nexport function defineRpcMiddleware<TContext = MiddlewareContext>(\n mw: MiddlewareFunction<TContext>,\n): MiddlewareFunction<TContext> {\n return mw;\n}\n\n// ─── Auth Definition & Composition ───────────────────────────────\n\n/**\n * Utility to define and strongly-type an AuthCallback function.\n * This provides immediate IDE autocomplete for the handshake and arguments.\n */\nexport function defineAuth<TSession = Record<string, unknown>>(\n cb: AuthCallback<TSession>,\n): AuthCallback<TSession> {\n return cb;\n}\n\n/**\n * Combines multiple AuthCallback functions sequentially.\n *\n * Flow matching standard middleware logic:\n * - If one callback `reject(err)` is called, the loop drops the connection instantly.\n * - If one callback `accept(opts)` is called, the loop terminates and grants the connection.\n * - If the loop finishes without anyone calling accept, it rejects with 401 Unauthorized.\n */\nexport function combineAuth(...cbs: AuthCallback[]): AuthCallback {\n return async (ctx) => {\n let accepted = false;\n let rejected = false;\n\n // Wrap the underlying accept/reject purely to detect when they fire\n const trackedAccept = (opts?: AuthAccept<any>) => {\n accepted = true;\n ctx.accept(opts);\n };\n\n const trackedReject = (code?: number, message?: string): never => {\n rejected = true;\n return ctx.reject(code, message);\n };\n\n const trackedCtx: import(\"../types.js\").AuthContext = {\n ...ctx,\n accept: trackedAccept,\n reject: trackedReject,\n };\n\n try {\n for (const cb of cbs) {\n if (ctx.signal.aborted || accepted || rejected) break;\n\n // Native callbacks from user might be sync or async\n const p = cb(trackedCtx);\n if (p instanceof Promise) {\n await p;\n }\n\n if (accepted || rejected) break;\n }\n\n // If loop finishes and nothing was explicitly decided, drop the connection\n if (!accepted && !rejected) {\n trackedReject(\n 401,\n \"Unauthorized (All composeAuth handlers passed without accepting)\",\n );\n }\n } catch (_err) {\n if (!rejected) {\n trackedReject(\n 500,\n \"Internal Server Error during auth compose execution\",\n );\n }\n }\n };\n}\n\n// ─── Logging Middleware ──────────────────────────────────────────\n\n/**\n * Creates a middleware that logs all RPC exchanges using the provided logger.\n * Logs start/end of calls and results with duration.\n */\nexport function createLoggingMiddleware(\n logger: LoggerLike,\n identity: string,\n config: LoggingConfig | boolean = {},\n): MiddlewareFunction<MiddlewareContext, any> {\n const options = typeof config === \"object\" ? config : {};\n const { exchangeLog = false, prettify = false } = options;\n\n return async (ctx, next) => {\n const start = Date.now();\n const method = ctx.method;\n\n // Use info if exchangeLog is enabled, otherwise debug\n const level = exchangeLog ? \"info\" : \"debug\";\n\n switch (ctx.type) {\n case \"incoming_call\":\n if (exchangeLog && prettify) {\n logger[level]?.(`⚡ ${identity} ← ${method} [IN]`, {\n messageId: ctx.messageId,\n method: ctx.method,\n protocol: ctx.protocol,\n payload: ctx.params,\n direction: \"IN\",\n });\n } else {\n logger[level]?.(`CALL ←`, {\n messageId: ctx.messageId,\n method: ctx.method,\n protocol: ctx.protocol,\n payload: ctx.params,\n direction: \"IN\",\n });\n }\n break;\n\n case \"outgoing_call\":\n if (exchangeLog && prettify) {\n logger[level]?.(`⚡ ${identity} → ${method} [OUT]`, {\n method: ctx.method,\n params: ctx.params,\n direction: \"OUT\",\n });\n } else {\n logger[level]?.(`CALL →`, {\n method: ctx.method,\n params: ctx.params,\n direction: \"OUT\",\n });\n }\n break;\n }\n\n try {\n const result = await next();\n const durationMs = Date.now() - start;\n\n switch (ctx.type) {\n case \"incoming_call\":\n if (result !== undefined && result !== null) {\n if (exchangeLog && prettify) {\n logger[level]?.(`✅ ${identity} → ${method} [RES]`, {\n messageId: ctx.messageId,\n method: ctx.method,\n durationMs,\n params: result,\n direction: \"OUT\",\n });\n } else {\n logger[level]?.(`CALLRESULT →`, {\n messageId: ctx.messageId,\n method: ctx.method,\n durationMs,\n params: result,\n direction: \"OUT\",\n });\n }\n }\n break;\n\n case \"outgoing_call\":\n if (exchangeLog && prettify) {\n logger[level]?.(`✅ ${identity} ← ${method} [RES]`, {\n messageId: (ctx as any).messageId,\n method: ctx.method,\n durationMs,\n payload: result,\n direction: \"IN\",\n });\n } else {\n logger[level]?.(`CALLRESULT ←`, {\n messageId: (ctx as any).messageId,\n method: ctx.method,\n durationMs,\n payload: result,\n direction: \"IN\",\n });\n }\n break;\n }\n\n return result;\n } catch (err) {\n const msg = (err as Error).message;\n const durationMs = Date.now() - start;\n\n if (ctx.type === \"incoming_call\") {\n if (exchangeLog && prettify) {\n logger.error?.(`🚨 ${identity} → ${method} [ERR]`, {\n messageId: ctx.messageId,\n method: ctx.method,\n durationMs,\n error: msg,\n direction: \"OUT\",\n });\n } else {\n logger.error?.(`CALLERROR →`, {\n messageId: ctx.messageId,\n method: ctx.method,\n durationMs,\n error: msg,\n direction: \"OUT\",\n });\n }\n } else if (ctx.type === \"outgoing_call\") {\n if (exchangeLog && prettify) {\n logger.warn?.(`🚨 ${identity} ← ${method} [ERR]`, {\n messageId: (ctx as any).messageId,\n method: ctx.method,\n durationMs,\n error: msg,\n direction: \"IN\",\n });\n } else {\n logger.warn?.(`CALLERROR ←`, {\n messageId: (ctx as any).messageId,\n method: ctx.method,\n durationMs,\n error: msg,\n direction: \"IN\",\n });\n }\n }\n throw err;\n }\n };\n}\n","/**\n * Middleware handling for intercepting and modifying OCPP operations.\n *\n * Implements an onion-model middleware stack (similar to Koa/Axios)\n * allowing cross-cutting concerns like logging, authentication, and validation.\n */\n\nexport type MiddlewareNext<TReturn = unknown> = () => Promise<TReturn>;\n\nexport type MiddlewareFunction<TContext, TReturn = unknown> = (\n context: TContext,\n next: MiddlewareNext<TReturn>,\n) => Promise<TReturn> | TReturn;\n\nexport class MiddlewareStack<TContext> {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n private _stack: MiddlewareFunction<TContext, any>[] = [];\n\n /**\n * Add a middleware function to the stack.\n */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n use<TReturn = any>(middleware: MiddlewareFunction<TContext, TReturn>): void {\n this._stack.push(middleware);\n }\n\n /**\n * Execute the middleware stack composed with a runner function.\n *\n * @param context The context object to pass through middleware\n * @param runner The final function to execute (the \"core\" logic)\n */\n async execute<TReturn = unknown>(\n context: TContext,\n runner: (context: TContext) => Promise<TReturn> | TReturn,\n ): Promise<TReturn> {\n let index = -1;\n\n const dispatch = async (i: number): Promise<TReturn> => {\n if (i <= index) {\n throw new Error(\"next() called multiple times\");\n }\n index = i;\n\n const fn = this._stack[i];\n\n if (i === this._stack.length) {\n return runner(context);\n }\n\n if (!fn) {\n return undefined as unknown as TReturn;\n }\n\n return fn(context, () => dispatch(i + 1));\n };\n\n return dispatch(0);\n }\n}\n","/**\n * Internal utility to initialize a logger from LoggingConfig.\n *\n * - `undefined` → default voltlog-io with console transport\n * - `false` → null (logging disabled)\n * - `LoggingConfig` → custom handler or configured voltlog-io\n */\n\nimport {\n consoleTransport,\n createLogger,\n type LogEntry,\n type LogLevelName,\n type LogMiddleware,\n prettyTransport,\n} from \"voltlog-io\";\nimport type { LoggerLike, LoggingConfig } from \"./types.js\";\n\n// ─── Display middleware ─────────────────────────────────────────\n\n/**\n * Check if any display option differs from its default.\n */\nfunction hasDisplayCustomization(config: LoggingConfig): boolean {\n return (\n config.showMetadata === false ||\n config.showSourceMeta === false ||\n config.prettifySource === true ||\n config.prettifyMetadata === true\n );\n}\n\n/**\n * Build a voltlog-io LogMiddleware that transforms context/meta\n * before the transport sees them, so prettyTransport's colors are preserved.\n *\n * Strategy:\n * - hide → clear the field so prettyTransport skips it\n * - prettify → embed a readable string into `entry.message` and clear the raw field\n */\nfunction buildDisplayMiddleware(config: LoggingConfig): LogMiddleware {\n const showMeta = config.showMetadata ?? true;\n const showSource = config.showSourceMeta ?? true;\n const prettySrc = config.prettifySource ?? false;\n const prettyMeta = config.prettifyMetadata ?? false;\n\n // ANSI color codes for prettification\n const DIM = \"\\x1b[2;37m\"; // dim white\n const RESET = \"\\x1b[0m\"; // reset all styles\n const CYAN = \"\\x1b[36m\"; // cyan\n\n return (entry: LogEntry, next: (e: LogEntry) => void) => {\n // ── Source context ──\n if (!showSource) {\n // Hide entirely\n entry.context = undefined;\n } else if (prettySrc && entry.context) {\n // Build compact tag like [OCPPServer/WT159]\n const parts: string[] = [];\n if (entry.context.component) parts.push(String(entry.context.component));\n if (entry.context.identity) parts.push(String(entry.context.identity));\n if (parts.length > 0) {\n // Embed into message and clear context\n entry.message = `${DIM}[${parts.join(\"/\")}]${RESET} ${entry.message}`;\n entry.context = undefined;\n }\n }\n\n // ── Trailing metadata ──\n const meta = entry.meta as Record<string, unknown> | undefined;\n if (!showMeta) {\n // Hide entirely\n entry.meta = {} as typeof entry.meta;\n } else if (prettyMeta && meta && Object.keys(meta).length > 0) {\n // Build key=value pairs, embed into message, clear meta\n const pairs = Object.entries(meta)\n .filter(([, v]) => v !== undefined && v !== null)\n .map(([k, v]) => {\n let valStr = typeof v === \"object\" ? JSON.stringify(v) : String(v);\n // Apply some basic dimming for non-string values or objects to keep it clean\n if (typeof v === \"string\") {\n valStr = `${DIM}${valStr}${RESET}`;\n } else {\n valStr = `${DIM}${valStr}${RESET}`;\n }\n return `${CYAN}${k}${RESET}=${valStr}`;\n })\n .join(\" \");\n if (pairs) {\n entry.message = `${entry.message} ${pairs}`;\n }\n entry.meta = {} as typeof entry.meta;\n }\n\n next(entry);\n };\n}\n\n// ─── Public API ─────────────────────────────────────────────────\n\n/**\n * Resolve a LoggingConfig | false | undefined into a LoggerLike or null.\n */\nexport function initLogger(\n config: LoggingConfig | false | undefined,\n defaultContext?: Record<string, unknown>,\n): LoggerLike | null {\n // Explicitly disabled\n if (config === false) return null;\n if (config?.enabled === false) return null;\n\n // Custom external logger provided — use as-is\n if (config?.logger) {\n if (defaultContext && config.logger.child) {\n return config.logger.child(defaultContext);\n }\n return config.logger;\n }\n\n // Build default voltlog-io\n const level = (config?.level ?? \"INFO\") as LogLevelName;\n const usePrettify = config?.prettify ?? false;\n\n const transports = usePrettify\n ? [prettyTransport({ level })]\n : [consoleTransport({ level })];\n\n if (config?.handler) {\n const customTransport = config.handler;\n transports.push({\n name: \"customHandler\",\n write: (entry) => customTransport(entry),\n });\n }\n\n // Build display middleware if any display options are set\n const middleware: LogMiddleware[] = [];\n if (config && hasDisplayCustomization(config)) {\n middleware.push(buildDisplayMiddleware(config));\n }\n\n const logger = createLogger({\n level,\n transports,\n middleware: middleware.length > 0 ? middleware : undefined,\n });\n\n // Bind default context (e.g. identity)\n if (defaultContext && Object.keys(defaultContext).length > 0) {\n return logger.child(defaultContext);\n }\n\n return logger;\n}\n","/**\n * Tiny browser-compatible typed EventEmitter.\n * Drop-in replacement for Node.js EventEmitter in browser contexts.\n */\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype Listener = (...args: any[]) => void;\n\nexport class EventEmitter {\n private _listeners = new Map<string, Listener[]>();\n\n on(event: string, listener: Listener): this {\n const arr = this._listeners.get(event);\n if (arr) {\n arr.push(listener);\n } else {\n this._listeners.set(event, [listener]);\n }\n return this;\n }\n\n once(event: string, listener: Listener): this {\n const wrapper: Listener = (...args) => {\n this.off(event, wrapper);\n listener(...args);\n };\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (wrapper as any).__wrapped = listener;\n return this.on(event, wrapper);\n }\n\n off(event: string, listener: Listener): this {\n const arr = this._listeners.get(event);\n if (!arr) return this;\n const idx = arr.findIndex(\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n (fn) => fn === listener || (fn as any).__wrapped === listener,\n );\n if (idx !== -1) arr.splice(idx, 1);\n if (arr.length === 0) this._listeners.delete(event);\n return this;\n }\n\n emit(event: string, ...args: unknown[]): boolean {\n const arr = this._listeners.get(event);\n if (!arr || arr.length === 0) return false;\n for (const fn of [...arr]) {\n fn(...args);\n }\n return true;\n }\n\n addListener(event: string, listener: Listener): this {\n return this.on(event, listener);\n }\n\n removeListener(event: string, listener: Listener): this {\n return this.off(event, listener);\n }\n\n removeAllListeners(event?: string): this {\n if (event) {\n this._listeners.delete(event);\n } else {\n this._listeners.clear();\n }\n return this;\n }\n\n listenerCount(event: string): number {\n return this._listeners.get(event)?.length ?? 0;\n }\n}\n","// ─── Base Errors ─────────────────────────────────────────────────\n\nexport class TimeoutError extends Error {\n constructor(message = \"Operation timed out\") {\n super(message);\n this.name = \"TimeoutError\";\n }\n}\n\n// ─── RPC Error Base ──────────────────────────────────────────────\n\nexport interface RPCError extends Error {\n readonly rpcErrorCode: string;\n readonly rpcErrorMessage: string;\n readonly details: Record<string, unknown>;\n}\n\nexport class RPCGenericError extends Error implements RPCError {\n readonly rpcErrorCode: string = \"GenericError\";\n readonly rpcErrorMessage: string = \"\";\n readonly details: Record<string, unknown>;\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message);\n this.name = \"RPCGenericError\";\n this.details = details;\n }\n}\n\n// ─── Specific RPC Errors ─────────────────────────────────────────\n\nexport class RPCNotImplementedError extends RPCGenericError {\n override readonly rpcErrorCode = \"NotImplemented\";\n override readonly rpcErrorMessage = \"Requested method is not known\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCNotImplementedError\";\n }\n}\n\nexport class RPCNotSupportedError extends RPCGenericError {\n override readonly rpcErrorCode = \"NotSupported\";\n override readonly rpcErrorMessage =\n \"Requested method is recognised but not supported\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCNotSupportedError\";\n }\n}\n\nexport class RPCInternalError extends RPCGenericError {\n override readonly rpcErrorCode = \"InternalError\";\n override readonly rpcErrorMessage =\n \"An internal error occurred and the receiver was not able to process the requested action successfully\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCInternalError\";\n }\n}\n\nexport class RPCProtocolError extends RPCGenericError {\n override readonly rpcErrorCode = \"ProtocolError\";\n override readonly rpcErrorMessage = \"Payload for action is incomplete\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCProtocolError\";\n }\n}\n\nexport class RPCSecurityError extends RPCGenericError {\n override readonly rpcErrorCode = \"SecurityError\";\n override readonly rpcErrorMessage =\n \"During the processing of action a security issue occurred preventing receiver from completing the action successfully\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCSecurityError\";\n }\n}\n\nexport class RPCFormationViolationError extends RPCGenericError {\n override readonly rpcErrorCode = \"FormationViolation\";\n override readonly rpcErrorMessage =\n \"Payload for action is syntactically incorrect or not conform the PDU structure for action\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCFormationViolationError\";\n }\n}\n\nexport class RPCFormatViolationError extends RPCGenericError {\n override readonly rpcErrorCode = \"FormatViolation\";\n override readonly rpcErrorMessage =\n \"Payload is syntactically correct but at least one field contains an invalid value\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCFormatViolationError\";\n }\n}\n\nexport class RPCPropertyConstraintViolationError extends RPCGenericError {\n override readonly rpcErrorCode = \"PropertyConstraintViolation\";\n override readonly rpcErrorMessage =\n \"Payload is syntactically correct but at least one of the fields violates data type constraints\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCPropertyConstraintViolationError\";\n }\n}\n\nexport class RPCOccurrenceConstraintViolationError extends RPCGenericError {\n override readonly rpcErrorCode = \"OccurrenceConstraintViolation\";\n override readonly rpcErrorMessage =\n \"Payload for action is syntactically correct but at least one of the fields violates occurrence constraints\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCOccurrenceConstraintViolationError\";\n }\n}\n\nexport class RPCTypeConstraintViolationError extends RPCGenericError {\n override readonly rpcErrorCode = \"TypeConstraintViolation\";\n override readonly rpcErrorMessage =\n \"Payload for action is syntactically correct but at least one of the fields violates type constraints\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCTypeConstraintViolationError\";\n }\n}\n\nexport class RPCMessageTypeNotSupportedError extends RPCGenericError {\n override readonly rpcErrorCode = \"MessageTypeNotSupported\";\n override readonly rpcErrorMessage =\n \"A message with a Message Type Number received that is not supported by this implementation\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCMessageTypeNotSupportedError\";\n }\n}\n\nexport class RPCFrameworkError extends RPCGenericError {\n override readonly rpcErrorCode = \"RpcFrameworkError\";\n override readonly rpcErrorMessage =\n \"Content of the call is not a valid RPC request\";\n\n constructor(message?: string, details: Record<string, unknown> = {}) {\n super(message, details);\n this.name = \"RPCFrameworkError\";\n }\n}\n","/**\n * A concurrency-limited async queue.\n * Enqueues async functions and executes them with a configurable concurrency limit.\n */\nexport class Queue {\n private _concurrency: number;\n private _running = 0;\n private _queue: Array<{\n fn: () => Promise<unknown>;\n resolve: (value: unknown) => void;\n reject: (reason: unknown) => void;\n }> = [];\n\n constructor(concurrency = 1) {\n this._concurrency = Math.max(1, concurrency);\n }\n\n get concurrency(): number {\n return this._concurrency;\n }\n\n get pending(): number {\n return this._queue.length;\n }\n\n get running(): number {\n return this._running;\n }\n\n get size(): number {\n return this._running + this._queue.length;\n }\n\n setConcurrency(concurrency: number): void {\n this._concurrency = Math.max(1, concurrency);\n this._drain();\n }\n\n push<T>(fn: () => Promise<T>): Promise<T> {\n return new Promise<T>((resolve, reject) => {\n this._queue.push({\n fn: fn as () => Promise<unknown>,\n resolve: resolve as (value: unknown) => void,\n reject,\n });\n this._drain();\n });\n }\n\n private _drain(): void {\n while (this._running < this._concurrency && this._queue.length > 0) {\n const item = this._queue.shift();\n this._running++;\n\n item\n ?.fn()\n .then(item.resolve)\n .catch(item.reject)\n .finally(() => {\n this._running--;\n this._drain();\n });\n }\n }\n}\n","import type { EventEmitter } from \"node:events\";\nimport type { IncomingMessage } from \"node:http\";\nimport type { Duplex } from \"node:stream\";\nimport type { TLSSocket } from \"node:tls\";\nimport type { LogEntry } from \"voltlog-io\";\nimport type {\n AllMethodNames,\n OCPPMethodMap,\n OCPPProtocolKey,\n OCPPRequestType,\n OCPPResponseType,\n} from \"./generated/index.js\";\nimport type { Validator } from \"./validator.js\";\n\nexport type {\n AllMethodNames,\n OCPPMethodMap,\n OCPPProtocolKey,\n OCPPRequestType,\n OCPPResponseType,\n};\n\n// ─── Typed EventEmitter ──────────────────────────────────────────\n\n/**\n * Utility type that overlays typed `.on()`, `.off()`, `.emit()` etc.\n * on top of Node.js EventEmitter. This is the foundation for type-safe\n * event handling throughout the library.\n */\nexport type TypedEventEmitter<\n TEvents extends Record<keyof TEvents, unknown[]>,\n> = Omit<\n EventEmitter,\n | \"on\"\n | \"once\"\n | \"off\"\n | \"emit\"\n | \"removeListener\"\n | \"addListener\"\n | \"removeAllListeners\"\n> & {\n on<K extends keyof TEvents | (string & {})>(\n event: K,\n listener: K extends keyof TEvents\n ? (...args: TEvents[K]) => void\n : (...args: unknown[]) => void,\n ): TypedEventEmitter<TEvents>;\n once<K extends keyof TEvents | (string & {})>(\n event: K,\n listener: K extends keyof TEvents\n ? (...args: TEvents[K]) => void\n : (...args: unknown[]) => void,\n ): TypedEventEmitter<TEvents>;\n off<K extends keyof TEvents | (string & {})>(\n event: K,\n listener: K extends keyof TEvents\n ? (...args: TEvents[K]) => void\n : (...args: unknown[]) => void,\n ): TypedEventEmitter<TEvents>;\n emit<K extends keyof TEvents | (string & {})>(\n event: K,\n ...args: K extends keyof TEvents ? TEvents[K] : unknown[]\n ): boolean;\n addListener<K extends keyof TEvents | (string & {})>(\n event: K,\n listener: K extends keyof TEvents\n ? (...args: TEvents[K]) => void\n : (...args: unknown[]) => void,\n ): TypedEventEmitter<TEvents>;\n removeListener<K extends keyof TEvents | (string & {})>(\n event: K,\n listener: K extends keyof TEvents\n ? (...args: TEvents[K]) => void\n : (...args: unknown[]) => void,\n ): TypedEventEmitter<TEvents>;\n removeAllListeners<K extends keyof TEvents | (string & {})>(\n event?: K,\n ): TypedEventEmitter<TEvents>;\n};\n\n// ─── OCPP Protocol ───────────────────────────────────────────────\n\nexport type OCPPProtocol = OCPPProtocolKey;\nexport type AnyOCPPProtocol = OCPPProtocol | (string & {});\n\n// ─── Connection State ────────────────────────────────────────────\n\nexport const ConnectionState = {\n CONNECTING: 0,\n OPEN: 1,\n CLOSING: 2,\n CLOSED: 3,\n} as const;\n\nexport type ConnectionState =\n (typeof ConnectionState)[keyof typeof ConnectionState];\n\n// ─── Security Profiles (OCPP Spec) ──────────────────────────────\n\nexport enum SecurityProfile {\n /** No security — plain WS, no auth (dev/testing only) */\n NONE = 0,\n /** Profile 1: Basic Auth over unsecured WS (ws://) — password-based */\n BASIC_AUTH = 1,\n /** Profile 2: TLS + Basic Auth (wss://) — server cert + password */\n TLS_BASIC_AUTH = 2,\n /** Profile 3: Mutual TLS (wss://) — client + server certificates */\n TLS_CLIENT_CERT = 3,\n}\n\n// ─── Message Types ───────────────────────────────────────────────\n\nexport const MessageType = {\n CALL: 2,\n CALLRESULT: 3,\n CALLERROR: 4,\n} as const;\n\nexport type MessageType = (typeof MessageType)[keyof typeof MessageType];\n\n// ─── OCPP Message Tuples ─────────────────────────────────────────\n\nexport type OCPPCall<T = unknown> = [2, string, string, T];\nexport type OCPPCallResult<T = unknown> = [3, string, T];\nexport type OCPPCallError = [\n 4,\n string,\n string,\n string,\n Record<string, unknown>,\n];\nexport type OCPPMessage<T = unknown> =\n | OCPPCall<T>\n | OCPPCallResult<T>\n | OCPPCallError;\n\n// ─── TLS Options ─────────────────────────────────────────────────\n\nexport interface TLSOptions {\n /** Server/client certificate (PEM) */\n cert?: string | Buffer;\n /** Private key (PEM) */\n key?: string | Buffer;\n /** CA certificate(s) for verification */\n ca?: string | Buffer | Array<string | Buffer>;\n /** Reject unauthorized certs (default: true) */\n rejectUnauthorized?: boolean;\n /** Passphrase for encrypted private key */\n passphrase?: string;\n}\n\n// ─── Handler Types ───────────────────────────────────────────────\n\nexport interface HandlerContext<T = unknown> {\n /** Unique message ID */\n messageId: string;\n /** OCPP method name (e.g. \"BootNotification\") */\n method: string;\n /** Active OCPP protocol version (e.g. \"ocpp1.6\") */\n protocol: string | undefined;\n /** Request parameters */\n params: T;\n /** Abort signal */\n signal: AbortSignal;\n}\n\nexport type CallHandler<TParams = unknown, TResult = unknown> = (\n context: HandlerContext<TParams>,\n) => TResult | Promise<TResult>;\n\nexport type WildcardHandler = (\n method: string,\n context: HandlerContext,\n) => unknown | Promise<unknown>;\n\nexport interface RouterHandlerContext<T = unknown> extends HandlerContext<T> {\n /** The specific server client that issued the message. */\n client: import(\"./server-client.js\").OCPPServerClient;\n}\n\nexport type RouterWildcardHandler = (\n method: string,\n context: RouterHandlerContext,\n) => unknown | Promise<unknown>;\n\n// ─── Call Options ────────────────────────────────────────────────\n\nexport interface CallOptions {\n /** Timeout in milliseconds for this specific call */\n timeoutMs?: number;\n /** Abort signal */\n signal?: AbortSignal;\n /**\n * Max retry attempts on TimeoutError (default: 0 = no retry).\n * Uses Full Jitter exponential backoff between retries.\n */\n retries?: number;\n /** Base delay in ms for exponential backoff between retries (default: 1000) */\n retryDelayMs?: number;\n /** Max delay cap in ms to prevent unbounded backoff (default: 30000) */\n retryMaxDelayMs?: number;\n /**\n * Idempotency key for deduplication. If provided, this value is used\n * as the OCPP messageId instead of generating a new random one.\n * Consumers can use the same key to guarantee exactly-once semantics\n * when retrying calls across reconnections.\n */\n idempotencyKey?: string;\n}\n\n// ─── Close Options ───────────────────────────────────────────────\n\nexport interface CloseOptions {\n /** WebSocket close code (default: 1000) */\n code?: number;\n /** Close reason string */\n reason?: string;\n /** Wait for pending calls to complete before closing */\n awaitPending?: boolean;\n /** Force-close without waiting */\n force?: boolean;\n}\n\n// ─── Handshake Info ──────────────────────────────────────────────\n\nexport interface HandshakeInfo {\n /** Charging station identity (from URL path) */\n identity: string;\n /** Remote IP address */\n remoteAddress: string;\n /** Request headers */\n headers: Record<string, string | string[] | undefined>;\n /** Negotiated subprotocols */\n protocols: Set<string>;\n /** Full URL pathname including params */\n pathname: string;\n /** Extracted dynamic route parameters */\n params: Record<string, string>;\n /** URL query parameters */\n query: URLSearchParams;\n /** Original HTTP request */\n request: IncomingMessage;\n /** Password from Basic Auth (Profile 1 & 2) */\n password?: Buffer;\n /** Client certificate (Profile 3 — mTLS) */\n clientCertificate?: ReturnType<TLSSocket[\"getPeerCertificate\"]>;\n /** Active security profile */\n securityProfile: SecurityProfile;\n}\n\n// ─── Session Data ────────────────────────────────────────────────\n\nexport type SessionData<T = Record<string, any>> = T;\n\n// ─── Logger Interface ────────────────────────────────────────────\n\n/**\n * Minimal logger contract — compatible with `console`, `pino`, `voltlog-io`,\n * or any custom object with these methods.\n *\n * All methods are optional so `console` works as-is.\n */\nexport interface LoggerLike {\n debug?(message: string, meta?: Record<string, unknown>): void;\n info?(message: string, meta?: Record<string, unknown>): void;\n warn?(message: string, meta?: Record<string, unknown>): void;\n error?(message: string, meta?: Record<string, unknown>): void;\n child?(context: Record<string, unknown>): LoggerLike;\n}\n\n/**\n * Minimal logger contract — compatible with `console`, `pino`, `voltlog-io`,\n * or any custom object with these methods.\n *\n * All methods are optional so `console` works as-is.\n * this is only not optional for the logger used by the library\n */\nexport interface LoggerLikeNotOptional {\n debug(message: string, meta?: Record<string, unknown>): void;\n info(message: string, meta?: Record<string, unknown>): void;\n warn(message: string, meta?: Record<string, unknown>): void;\n error(message: string, meta?: Record<string, unknown>): void;\n child(context: Record<string, unknown>): LoggerLike;\n}\n\n/**\n * Logging configuration for OCPPClient and OCPPServer.\n *\n * @example Default (auto console logging)\n * ```ts\n * const client = new OCPPClient({ identity: 'CP-101', endpoint: '...' });\n * // → Logs to console via voltlog-io by default\n * ```\n *\n * @example Disable logging\n * ```ts\n * new OCPPClient({ identity: 'CP-101', endpoint: '...', logging: false });\n * ```\n *\n * @example Custom logger\n * ```ts\n * new OCPPClient({ identity: 'CP-101', endpoint: '...', logging: { handler: pino() } });\n * ```\n */\nexport interface LoggingConfig {\n /** Enable/disable logging (default: true) */\n enabled?: boolean;\n /**\n * Enable OCPP exchange logging (default: false).\n * Adds `direction: 'IN' | 'OUT'` to OCPP message logs.\n * When combined with `prettify`, renders styled exchange lines:\n * `⚡ CP-101 → BootNotification [IN]`\n */\n exchangeLog?: boolean;\n /**\n * Enable pretty-printed colored output (default: false).\n * Uses voltlog-io's prettyTransport with icons, colors, and timestamps.\n * Without this, logs are structured JSON.\n */\n prettify?: boolean;\n /** Log level for the default voltlog-io logger (default: 'INFO') */\n level?: string;\n /** Custom logger — replaces the default voltlog-io entirely */\n logger?: LoggerLike;\n /** Custom VoltLog transport function — receives formatted logs */\n handler?: (entry: LogEntry) => void | Promise<void>;\n\n // ─── Display Options (only apply to default voltlog-io logger) ──\n\n /**\n * Show trailing metadata object in log output (default: true).\n * `INFO Server listening {\"port\":5000,\"host\":\"0.0.0.0\"}`\n * ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ← hidden when false\n */\n showMetadata?: boolean;\n /**\n * Show source context object in log output (default: true).\n * `INFO Server listening {\"component\":\"OCPPServer\"} {\"port\":5000}`\n * ^^^^^^^^^^^^^^^^^^^^^^^^ ← hidden when false\n */\n showSourceMeta?: boolean;\n /**\n * Prettify source context into a compact tag (default: false).\n * `{\"component\":\"OCPPServer\",\"identity\":\"CP-1\"}` → `[OCPPServer/CP-1]`\n */\n prettifySource?: boolean;\n /**\n * Prettify trailing metadata into readable key=value pairs (default: false).\n * `{\"port\":5000,\"host\":\"0.0.0.0\"}` → `port=5000 host=0.0.0.0`\n */\n prettifyMetadata?: boolean;\n}\n\n// ─── Client Options ──────────────────────────────────────────────\n\nexport interface ClientOptions {\n /** Unique identity for this client (charging station ID) */\n identity: string;\n /** WebSocket endpoint URL (ws:// or wss://) */\n endpoint: string;\n /** OCPP Security Profile (default: NONE) */\n securityProfile?: SecurityProfile;\n /** Password for Basic Auth (Profile 1 & 2) */\n password?: string | Buffer;\n /** TLS options (Profile 2 & 3) */\n tls?: TLSOptions;\n /** OCPP subprotocols to negotiate */\n protocols?: AnyOCPPProtocol[];\n /** Additional WebSocket headers */\n headers?: Record<string, string>;\n /** Additional query parameters */\n query?: Record<string, string>;\n /** Enable automatic reconnection (default: true) */\n reconnect?: boolean;\n /** Maximum reconnection attempts (default: Infinity) */\n maxReconnects?: number;\n /** Back-off base delay in ms (default: 1000) */\n backoffMin?: number;\n /** Back-off max delay in ms (default: 30000) */\n backoffMax?: number;\n /** Call timeout in ms (default: 30000) */\n callTimeoutMs?: number;\n /** Ping interval in ms (default: 30000, 0 to disable) */\n pingIntervalMs?: number;\n /** Defer pings if activity detected (default: false) */\n deferPingsOnActivity?: boolean;\n /**\n * Pong response timeout in ms. If no pong is received within this\n * window after a ping, the connection is considered dead and terminated.\n * (default: pingIntervalMs + 5000, 0 to disable)\n */\n pongTimeoutMs?: number;\n /** Maximum concurrent outbound calls (default: 1) */\n callConcurrency?: number;\n /** Enable strict mode validation (default: false) */\n strictMode?: boolean | OCPPProtocol[];\n /** If defined, restricts strict mode validation ONLY to these methods */\n strictModeMethods?: Array<AllMethodNames<OCPPProtocol>>;\n /** Custom validators for strict mode */\n strictModeValidators?: Validator[];\n /** Max number of bad messages before closing (default: Infinity) */\n maxBadMessages?: number;\n /** Include error details in responses (default: false) */\n respondWithDetailedErrors?: boolean;\n /**\n * Logging configuration.\n * - `undefined` / not set → default voltlog-io with console (logging enabled)\n * - `false` → logging disabled entirely\n * - `LoggingConfig` → custom configuration\n */\n logging?: LoggingConfig | false;\n /** Rate Limiting configuration (Token Bucket) */\n rateLimit?: RateLimitOptions;\n /**\n * If true, calls made while disconnected are queued in-memory\n * and flushed automatically on reconnect. (default: false)\n */\n offlineQueue?: boolean;\n /**\n * Maximum number of messages to queue while offline.\n * Oldest messages are dropped when exceeded. (default: 100)\n */\n offlineQueueMaxSize?: number;\n}\n\n// ─── Rate Limit Options ──────────────────────────────────────────\n\nexport interface RateLimitOptions {\n /** Maximum number of messages allowed within the window */\n limit: number;\n /** Window size in milliseconds */\n windowMs: number;\n /**\n * Action to take when rate limit is exceeded.\n * - 'disconnect': Terminate the socket immediately (hard enforce).\n * - 'ignore': Drop the message entirely, letting the client back-off and retry.\n * - Custom callback: Perform custom logging or logic when exceeded.\n * (default: 'ignore')\n */\n onLimitExceeded?:\n | \"disconnect\"\n | \"ignore\"\n | ((\n client: import(\"./server-client.js\").OCPPServerClient,\n rawData: unknown,\n ) => void | Promise<void>);\n /**\n * Specific limits applied purely to individual methods (e.g. Heartbeat, BootNotification).\n * Note: The method must be parsed from the raw JSON payload to apply this.\n */\n methods?: Record<string, { limit: number; windowMs: number }>;\n}\n\n// ─── Router Options ──────────────────────────────────────────────\n\nexport interface RouterConfig {\n /** Accepted OCPP subprotocols (e.g. [\"ocpp1.6\"]) */\n protocols?: AnyOCPPProtocol[];\n /** Call timeout in ms — overrides server default */\n callTimeoutMs?: number;\n /** Ping interval in ms — overrides server default */\n pingIntervalMs?: number;\n /** Defer pings if activity detected — overrides server default */\n deferPingsOnActivity?: boolean;\n /** Max concurrent outbound calls — overrides server default */\n callConcurrency?: number;\n /** Enable strict mode validation — overrides server default */\n strictMode?: boolean | OCPPProtocol[];\n /** If defined, restricts strict mode validation ONLY to these methods */\n strictModeMethods?: Array<AllMethodNames<OCPPProtocol>>;\n /** Rate Limiting configuration — overrides server default */\n rateLimit?: RateLimitOptions;\n}\n\nexport interface CORSOptions {\n /** Allowed IPv4, IPv6, or CIDR ranges (e.g. \"10.0.0.0/8\") */\n allowedIPs?: string[];\n /** Allowed Origin header values (e.g. \"https://dashboard.example.com\") */\n allowedOrigins?: string[];\n /** Allowed WebSocket protocol schemes */\n allowedSchemes?: (\"ws\" | \"wss\")[];\n}\n\n// ─── Server Options ──────────────────────────────────────────────\n\nexport interface ServerOptions {\n /** OCPP Security Profile (default: NONE) */\n securityProfile?: SecurityProfile;\n /** TLS options for HTTPS server (Profile 2 & 3) */\n tls?: TLSOptions;\n /** Accepted OCPP subprotocols */\n protocols?: AnyOCPPProtocol[];\n /** Call timeout in ms — inherited by server clients (default: 30000) */\n callTimeoutMs?: number;\n /** Ping interval in ms — inherited by server clients (default: 30000) */\n pingIntervalMs?: number;\n /** Defer pings if activity detected — inherited (default: false) */\n deferPingsOnActivity?: boolean;\n /** Max concurrent outbound calls — inherited (default: 1) */\n callConcurrency?: number;\n /** Enable strict mode — inherited (default: false) */\n strictMode?: boolean | OCPPProtocol[];\n /** If defined, restricts strict mode validation ONLY to these methods */\n strictModeMethods?: Array<AllMethodNames<OCPPProtocol>>;\n /** Custom validators — inherited */\n strictModeValidators?: Validator[];\n /** Rate Limiting configuration — inherited */\n rateLimit?: RateLimitOptions;\n /** Max bad messages — inherited (default: Infinity) */\n maxBadMessages?: number;\n /** Include error details in responses — inherited (default: false) */\n respondWithDetailedErrors?: boolean;\n /**\n * Session inactivity timeout in milliseconds before garbage collection.\n * (default: 7200000 / 2 hours)\n */\n sessionTtlMs?: number;\n /**\n * Maximum time (ms) to wait for the auth callback to resolve during\n * a WebSocket upgrade handshake. If the callback does not settle within\n * this window, the socket is destroyed and an `upgradeAborted` event\n * is emitted. Set to `0` to disable. (default: 30000)\n */\n handshakeTimeoutMs?: number;\n /**\n * Logging configuration — inherited by server clients.\n * - `undefined` / not set → default voltlog-io with console\n * - `false` → logging disabled\n * - `LoggingConfig` → custom configuration\n */\n logging?: LoggingConfig | false;\n /**\n * Connection-level rate limiting (per-IP) applied at the HTTP upgrade boundary,\n * before any auth, TLS or JSON parsing occurs — blocks DDoS connection floods in ~1µs.\n * - `limit`: Max upgrade requests per IP within `windowMs` (default: 20)\n * - `windowMs`: Sliding window in ms (default: 10000)\n */\n connectionRateLimit?: {\n limit: number;\n windowMs: number;\n };\n /**\n * Maximum number of inactive sessions to retain in the bounded LRU cache.\n * Prevents OOM under DDoS or reconnection storms with transient identities.\n * (default: 50000)\n */\n maxSessions?: number;\n /**\n * Enable the built-in HTTP health/metrics endpoint.\n * When enabled, non-upgrade HTTP requests to `/health` return a JSON health check,\n * and requests to `/metrics` return Prometheus-compatible text metrics.\n * (default: false)\n */\n healthEndpoint?: boolean;\n /**\n * I1: Maximum WebSocket payload size in bytes. Messages exceeding this limit\n * are rejected at the transport layer before JSON parsing, preventing OOM\n * from oversized or malicious payloads.\n * (default: 65536 / 64KB — sufficient for any standard OCPP message)\n */\n maxPayloadBytes?: number;\n}\n\n// ─── Observability ─────────────────────────────────────────────────\n\nexport interface OCPPServerStats {\n /** Number of currently connected WebSockets */\n connectedClients: number;\n /** Number of active memory sessions */\n activeSessions: number;\n /** Process uptime in seconds */\n uptimeSeconds: number;\n /** Process Memory Usage (bytes) */\n memoryUsage: NodeJS.MemoryUsage;\n /** Process CPU Time (microseconds) */\n cpuUsage: NodeJS.CpuUsage;\n /** Process ID */\n pid: number;\n /** Low-level WebSocket Server metrics */\n webSockets?: {\n /** Total active clients managed by the underlying ws server */\n total: number;\n /** Current messages waiting to be flushed to network (bytes) */\n bufferedAmount: number;\n };\n}\n\n// ─── Listen Options ──────────────────────────────────────────────\n\nexport interface ListenOptions {\n /** Existing HTTP/HTTPS server to attach to */\n server?: import(\"node:http\").Server | import(\"node:https\").Server;\n /** Hostname to bind to */\n host?: string;\n /** Signal to abort the listen */\n signal?: AbortSignal;\n}\n\n// ─── Auth Callback ───────────────────────────────────────────────\n\nexport interface AuthAccept<TSession = Record<string, unknown>> {\n /** Subprotocol to use for this client */\n protocol?: string;\n /** Session data attached to the client */\n session?: TSession;\n}\n\nexport type AuthCallback<TSession = Record<string, unknown>> = (\n ctx: AuthContext<TSession>,\n) => void | Promise<void>;\n\nexport type RoutePattern = string | RegExp;\n\nexport interface AuthRoute {\n pattern: RoutePattern | null; // null represents the default fallback route\n handler: AuthCallback<any>;\n}\n\n// ─── Event Types ─────────────────────────────────────────────────\n\nexport interface ClientEvents {\n open: [{ response: IncomingMessage }];\n close: [{ code: number; reason: string }];\n disconnect: [{ code: number; reason: string }];\n error: [Error];\n connecting: [{ url: string }];\n reconnect: [{ attempt: number; delay: number }];\n message: [OCPPMessage];\n call: [OCPPCall];\n callResult: [OCPPCallResult];\n callError: [OCPPCallError];\n badMessage: [{ message: string; error: Error }];\n ping: [];\n pong: [];\n strictValidationFailure: [{ message: unknown; error: Error }];\n}\n\nimport type { OCPPServerClient } from \"./server-client.js\";\n\n/**\n * I3: Structured security event for SIEM integration.\n * Emitted by the server for audit-relevant actions.\n */\nexport interface SecurityEvent {\n /** Event type identifier */\n type:\n | \"AUTH_FAILED\"\n | \"RATE_LIMIT_EXCEEDED\"\n | \"UPGRADE_ABORTED\"\n | \"CONNECTION_RATE_LIMIT\"\n | \"INVALID_PAYLOAD\";\n /** Station identity (if known) */\n identity?: string;\n /** Remote IP address */\n ip?: string;\n /** ISO 8601 timestamp */\n timestamp: string;\n /** Event-specific details */\n details?: Record<string, unknown>;\n}\n\nexport interface ServerEvents {\n client: [OCPPServerClient];\n error: [Error];\n upgradeError: [{ error: Error; socket: Duplex }];\n upgradeAborted: [\n {\n identity: string;\n reason: string;\n socket: Duplex;\n request: IncomingMessage;\n },\n ];\n closing: [];\n close: [];\n /** I3: Structured security event for SIEM/audit pipelines */\n securityEvent: [SecurityEvent];\n // Native WebSocketServer events\n connection: [\n socket: import(\"ws\").WebSocket,\n request: import(\"node:http\").IncomingMessage,\n ];\n listening: [];\n headers: [headers: string[], request: import(\"node:http\").IncomingMessage];\n}\n\n// ─── Event Adapter Interface ─────────────────────────────────────\n\nexport interface EventAdapterInterface {\n publish(channel: string, data: unknown): Promise<void>;\n publishBatch?(messages: { channel: string; data: unknown }[]): Promise<void>;\n subscribe(channel: string, handler: (data: unknown) => void): Promise<void>;\n unsubscribe(channel: string): Promise<void>;\n disconnect(): Promise<void>;\n\n // Presence Registry (Optional)\n setPresence?(identity: string, nodeId: string, ttl: number): Promise<void>;\n getPresence?(identity: string): Promise<string | null>;\n getPresenceBatch?(identities: string[]): Promise<(string | null)[]>;\n removePresence?(identity: string): Promise<void>;\n /**\n * Batch set multiple presence entries in a single pipeline.\n * Reduces N network round-trips to 1 for bulk presence updates.\n */\n setPresenceBatch?(\n entries: { identity: string; nodeId: string; ttl?: number }[],\n ): Promise<void>;\n\n // Observability Pipeline (Optional)\n metrics?(): Promise<Record<string, unknown>>;\n}\n\n// ─── Symbols ─────────────────────────────────────────────────────\n\nexport const NOREPLY: unique symbol = Symbol(\"NOREPLY\");\n// ─── Middleware ──────────────────────────────────────────────────\n\nexport type MiddlewareContext =\n | {\n type: \"incoming_call\";\n messageId: string;\n method: string;\n params: unknown;\n protocol?: string;\n }\n | {\n type: \"outgoing_call\";\n messageId: string;\n method: string;\n params: unknown;\n options: CallOptions;\n }\n | {\n type: \"incoming_result\";\n messageId: string;\n payload: unknown;\n method: string; // Correlated method name\n }\n | {\n type: \"incoming_error\";\n messageId: string;\n error: OCPPCallError;\n method: string; // Correlated method name\n };\n\nexport type { MiddlewareFunction, MiddlewareNext } from \"./middleware.js\";\n\n// ─── Router Component Types ──────────────────────────────────────────\n\nexport interface BaseConnectionContext {\n /** The handshake info from the upgrading WebSocket request */\n handshake: HandshakeInfo;\n /** Modifiable record object suitable for passing data between middlewares (e.g. auth tokens) */\n state: Record<string, unknown>;\n /** Safely reject the WebSocket connection explicitly with an HTTP code and reason */\n reject: (code?: number, message?: string) => never;\n}\n\nexport interface ConnectionContext extends BaseConnectionContext {\n /** Triggers the next middleware in the execution chain, optionally merging a payload into ctx.state */\n next: (payload?: Record<string, unknown>) => Promise<void>;\n}\n\nexport interface AuthContext<TSession = Record<string, unknown>>\n extends BaseConnectionContext {\n /** The AbortSignal representing if the client abruptly closed the underlying socket */\n signal: AbortSignal;\n /** Grants the connection and optionally sets the negotiated protocol or session metadata */\n accept: (options?: AuthAccept<TSession>) => void;\n}\n\nexport type ConnectionMiddleware = (\n ctx: ConnectionContext,\n) => Promise<void> | void;\n","import type { RPCError } from \"./errors.js\";\nimport * as errors from \"./errors.js\";\nimport type { LoggerLikeNotOptional } from \"./types.js\";\n\n// ─── RPC Error Factory ──────────────────────────────────────────\n\n/**\n * Registry mapping OCPP-J RPC error code strings to their corresponding\n * error constructors. Organized by OCPP spec error category.\n */\nconst RPC_ERROR_REGISTRY = new Map<\n string,\n new (\n message?: string,\n details?: Record<string, unknown>,\n ) => RPCError\n>([\n // Generic / framework errors\n [\"GenericError\", errors.RPCGenericError],\n [\"RpcFrameworkError\", errors.RPCFrameworkError],\n [\"MessageTypeNotSupported\", errors.RPCMessageTypeNotSupportedError],\n\n // Action-level errors\n [\"NotImplemented\", errors.RPCNotImplementedError],\n [\"NotSupported\", errors.RPCNotSupportedError],\n [\"InternalError\", errors.RPCInternalError],\n\n // Protocol / security errors\n [\"ProtocolError\", errors.RPCProtocolError],\n [\"SecurityError\", errors.RPCSecurityError],\n\n // Payload validation errors\n [\"FormatViolation\", errors.RPCFormatViolationError],\n [\"FormationViolation\", errors.RPCFormationViolationError],\n [\"PropertyConstraintViolation\", errors.RPCPropertyConstraintViolationError],\n [\n \"OccurrenceConstraintViolation\",\n errors.RPCOccurrenceConstraintViolationError,\n ],\n [\"TypeConstraintViolation\", errors.RPCTypeConstraintViolationError],\n]);\n\n/**\n * Instantiate a typed RPCError from a string error code.\n * Returns an RPCGenericError if the code is not recognized.\n */\nexport function createRPCError(\n code: string,\n message?: string,\n details: Record<string, unknown> = {},\n): RPCError {\n const Ctor = RPC_ERROR_REGISTRY.get(code) ?? errors.RPCGenericError;\n return new Ctor(message, details);\n}\n\n// ─── Error Serialization ────────────────────────────────────────\n\n/**\n * Known error properties to extract, in a defined order.\n * This covers standard Error fields plus common OCPP RPC fields.\n */\nconst ERROR_PROPERTIES = [\n \"name\",\n \"message\",\n \"stack\",\n \"code\",\n \"rpcErrorCode\",\n \"rpcErrorMessage\",\n \"details\",\n] as const;\n\n/**\n * Convert an Error (or subclass) into a plain, JSON-safe object.\n *\n * Extracts well-known properties explicitly rather than relying on\n * Object.getOwnPropertyNames to avoid exposing internal fields and\n * to guarantee a stable output shape.\n *\n * If a property holds a non-serializable value (functions, symbols,\n * circular references), it is silently skipped.\n */\nexport function getErrorPlainObject(err: Error): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const prop of ERROR_PROPERTIES) {\n const value = (err as unknown as Record<string, unknown>)[prop];\n if (value !== undefined) {\n // Skip functions and symbols — they aren't JSON-serializable\n if (typeof value === \"function\" || typeof value === \"symbol\") continue;\n\n // Test serializability for complex values\n if (typeof value === \"object\" && value !== null) {\n try {\n JSON.stringify(value);\n result[prop] = value;\n } catch {\n // Skip non-serializable properties (circular refs, etc.)\n }\n } else {\n result[prop] = value;\n }\n }\n }\n\n // Ensure we always have at least name and message\n if (!result.name) result.name = err.name;\n if (!result.message) result.message = err.message;\n\n return result;\n}\n\n// ─── Package Identity ───────────────────────────────────────────\n\nconst PKG_NAME = \"ocpp-ws-io\";\nconst PKG_VERSION = \"1.0.1\";\n\n/**\n * Get the package identifier string used in HTTP headers and logging.\n * Format: `ocpp-ws-io/1.0.0`\n */\nexport function getPackageIdent(): string {\n return `${PKG_NAME}/${PKG_VERSION}`;\n}\n\n/* \n No-op logger for when logging is disabled.\n \n*/\nexport const NOOP_LOGGER: LoggerLikeNotOptional = {\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n child: () => NOOP_LOGGER,\n};\n","import type { RPCError } from \"./errors.js\";\nimport * as errors from \"./errors.js\";\n\nexport { NOOP_LOGGER } from \"../util.js\";\n\n// ─── RPC Error Factory ──────────────────────────────────────────\n\nconst RPC_ERROR_REGISTRY = new Map<\n string,\n new (\n message?: string,\n details?: Record<string, unknown>,\n ) => RPCError\n>([\n [\"GenericError\", errors.RPCGenericError],\n [\"RpcFrameworkError\", errors.RPCFrameworkError],\n [\"MessageTypeNotSupported\", errors.RPCMessageTypeNotSupportedError],\n [\"NotImplemented\", errors.RPCNotImplementedError],\n [\"NotSupported\", errors.RPCNotSupportedError],\n [\"InternalError\", errors.RPCInternalError],\n [\"ProtocolError\", errors.RPCProtocolError],\n [\"SecurityError\", errors.RPCSecurityError],\n [\"FormatViolation\", errors.RPCFormatViolationError],\n [\"FormationViolation\", errors.RPCFormationViolationError],\n [\"PropertyConstraintViolation\", errors.RPCPropertyConstraintViolationError],\n [\n \"OccurrenceConstraintViolation\",\n errors.RPCOccurrenceConstraintViolationError,\n ],\n [\"TypeConstraintViolation\", errors.RPCTypeConstraintViolationError],\n]);\n\n/**\n * Instantiate a typed RPCError from a string error code.\n * Returns an RPCGenericError if the code is not recognized.\n */\nexport function createRPCError(\n code: string,\n message?: string,\n details: Record<string, unknown> = {},\n): RPCError {\n const Ctor = RPC_ERROR_REGISTRY.get(code) ?? errors.RPCGenericError;\n return new Ctor(message, details);\n}\n\n// ─── Error Serialization ────────────────────────────────────────\n\nconst ERROR_PROPERTIES = [\n \"name\",\n \"message\",\n \"stack\",\n \"code\",\n \"rpcErrorCode\",\n \"rpcErrorMessage\",\n \"details\",\n] as const;\n\n/**\n * Convert an Error into a plain, JSON-safe object.\n */\nexport function getErrorPlainObject(err: Error): Record<string, unknown> {\n const result: Record<string, unknown> = {};\n\n for (const prop of ERROR_PROPERTIES) {\n const value = (err as unknown as Record<string, unknown>)[prop];\n if (value !== undefined) {\n if (typeof value === \"function\" || typeof value === \"symbol\") continue;\n\n if (typeof value === \"object\" && value !== null) {\n try {\n JSON.stringify(value);\n result[prop] = value;\n } catch {\n // Skip non-serializable\n }\n } else {\n result[prop] = value;\n }\n }\n }\n\n if (!result.name) result.name = err.name;\n if (!result.message) result.message = err.message;\n\n return result;\n}\n","/// <reference lib=\"dom\" />\n\n/**\n * BrowserOCPPClient — A full-featured browser WebSocket RPC client for OCPP.\n *\n * Feature-complete port of OCPPClient for browser environments:\n * - Typed event emitter (no Node.js EventEmitter dependency)\n * - Auto-reconnection with exponential backoff + jitter\n * - Concurrency-limited call queue\n * - Version-specific & wildcard handlers\n * - Abort signal support\n * - Bad message handling\n * - NOREPLY support\n */\nimport { initLogger } from \"../init-logger.js\";\nimport { type MiddlewareFunction, MiddlewareStack } from \"../middleware.js\";\nimport type { MiddlewareContext } from \"../types.js\";\nimport { EventEmitter } from \"./emitter.js\";\nimport {\n type RPCError,\n RPCGenericError,\n RPCMessageTypeNotSupportedError,\n TimeoutError,\n} from \"./errors.js\";\nimport { Queue } from \"./queue.js\";\nimport {\n type AllMethodNames,\n type BrowserClientOptions,\n type CallHandler,\n type CallOptions,\n type CloseOptions,\n ConnectionState,\n type HandlerContext,\n type LoggerLike,\n type LoggerLikeNotOptional,\n MessageType,\n NOREPLY,\n type OCPPCall,\n type OCPPCallError,\n type OCPPCallResult,\n type OCPPMessage,\n type OCPPProtocol,\n type OCPPRequestType,\n type OCPPResponseType,\n type WildcardHandler,\n} from \"./types.js\";\nimport { createRPCError, getErrorPlainObject, NOOP_LOGGER } from \"./util.js\";\n\nconst { CONNECTING, OPEN, CLOSING, CLOSED } = ConnectionState;\n\ninterface PendingCall {\n resolve: (value: unknown) => void;\n reject: (reason: unknown) => void;\n timeoutHandle: ReturnType<typeof setTimeout>;\n abortHandler?: () => void;\n method: string;\n sentAt: number;\n}\n\n/**\n * BrowserOCPPClient — A typed WebSocket RPC client for OCPP in browser environments.\n *\n * API-compatible with `OCPPClient` from `ocpp-ws-io`, adapted for the browser\n * WebSocket API (no Node.js dependencies).\n *\n * @example\n * ```ts\n * import { BrowserOCPPClient } from \"ocpp-ws-io/browser\";\n *\n * const client = new BrowserOCPPClient({\n * identity: \"CP001\",\n * endpoint: \"wss://central.example.com/ocpp\",\n * protocols: [\"ocpp1.6\"],\n * });\n *\n * client.on(\"open\", () => console.log(\"Connected!\"));\n * await client.connect();\n * ```\n */\nexport class BrowserOCPPClient<\n P extends OCPPProtocol = OCPPProtocol,\n> extends EventEmitter {\n // Static connection states\n static readonly CONNECTING = CONNECTING;\n static readonly OPEN = OPEN;\n static readonly CLOSING = CLOSING;\n static readonly CLOSED = CLOSED;\n\n private _options: Required<\n Pick<\n BrowserClientOptions,\n | \"identity\"\n | \"endpoint\"\n | \"callTimeoutMs\"\n | \"callConcurrency\"\n | \"maxBadMessages\"\n | \"respondWithDetailedErrors\"\n | \"reconnect\"\n | \"maxReconnects\"\n | \"backoffMin\"\n | \"backoffMax\"\n >\n > &\n BrowserClientOptions;\n\n private _state: (typeof ConnectionState)[keyof typeof ConnectionState] =\n CLOSED;\n private _ws: WebSocket | null = null;\n private _protocol: string | undefined;\n private _identity: string;\n\n private _handlers = new Map<string, CallHandler>();\n private _wildcardHandler: WildcardHandler | null = null;\n private _pendingCalls = new Map<string, PendingCall>();\n private _pendingResponses = new Set<string>();\n private _callQueue: Queue;\n private _closePromise: Promise<{ code: number; reason: string }> | null =\n null;\n private _reconnectAttempt = 0;\n private _reconnectTimer: ReturnType<typeof setTimeout> | null = null;\n private _badMessageCount = 0;\n private _outboundBuffer: string[] = [];\n private _logger: LoggerLike;\n private _middleware: MiddlewareStack<MiddlewareContext>;\n\n constructor(options: BrowserClientOptions) {\n super();\n\n if (!options.identity) {\n throw new Error(\"identity is required\");\n }\n\n this._identity = options.identity;\n\n this._options = {\n reconnect: true,\n maxReconnects: Infinity,\n backoffMin: 1000,\n backoffMax: 30000,\n callTimeoutMs: 30000,\n callConcurrency: 1,\n maxBadMessages: Infinity,\n respondWithDetailedErrors: false,\n ...options,\n };\n\n this._callQueue = new Queue(this._options.callConcurrency);\n this._middleware = new MiddlewareStack<MiddlewareContext>();\n\n // Initialize logger\n const loggerInstance = initLogger(this._options.logging, {\n component: \"BrowserOCPPClient\",\n identity: this._identity,\n });\n this._logger = loggerInstance || NOOP_LOGGER;\n }\n\n // ─── Getters ─────────────────────────────────────────────────\n\n get log(): LoggerLikeNotOptional {\n return this._logger as LoggerLikeNotOptional;\n }\n get identity(): string {\n return this._identity;\n }\n get protocol(): string | undefined {\n return this._protocol;\n }\n get state(): (typeof ConnectionState)[keyof typeof ConnectionState] {\n return this._state;\n }\n\n // ─── Connect ─────────────────────────────────────────────────\n\n async connect(): Promise<void> {\n if (this._state !== CLOSED) {\n throw new Error(`Cannot connect: client is in state ${this._state}`);\n }\n\n this._state = CONNECTING;\n this._reconnectAttempt = 0;\n\n return this._connectInternal();\n }\n\n private async _connectInternal(): Promise<void> {\n return new Promise<void>((resolve, reject) => {\n const endpoint = this._buildEndpoint();\n\n this._logger.debug?.(\"Connecting\", { url: endpoint });\n this.emit(\"connecting\", { url: endpoint });\n\n let ws: WebSocket;\n try {\n ws = this._options.protocols?.length\n ? new WebSocket(endpoint, this._options.protocols)\n : new WebSocket(endpoint);\n } catch (err) {\n this._state = CLOSED;\n reject(err);\n return;\n }\n this._ws = ws;\n\n const onOpen = (event: Event) => {\n cleanup();\n this._state = OPEN;\n this._protocol = ws.protocol || undefined;\n this._badMessageCount = 0;\n\n // Narrow protocols to negotiated protocol for future reconnects\n if (ws.protocol && this._reconnectAttempt === 0) {\n this._options.protocols = [ws.protocol];\n }\n\n this._attachWebsocket(ws);\n\n // Flush outbound buffer (messages queued during CONNECTING)\n if (this._outboundBuffer.length > 0) {\n const buffer = this._outboundBuffer;\n this._outboundBuffer = [];\n for (const msg of buffer) this._ws?.send(msg);\n }\n\n this._logger.info?.(\"Connected\", {\n protocol: ws.protocol || undefined,\n });\n this.emit(\"open\", event);\n resolve();\n };\n\n const onError = (event: Event) => {\n cleanup();\n this._state = CLOSED;\n this._logger.error?.(\"Connection error\");\n this.emit(\"error\", event);\n reject(event);\n };\n\n const onClose = () => {\n cleanup();\n if (this._state === CONNECTING) {\n this._state = CLOSED;\n reject(new Error(\"WebSocket closed during connection\"));\n }\n };\n\n const cleanup = () => {\n ws.removeEventListener(\"open\", onOpen);\n ws.removeEventListener(\"error\", onError);\n ws.removeEventListener(\"close\", onClose);\n };\n\n ws.addEventListener(\"open\", onOpen);\n ws.addEventListener(\"error\", onError);\n ws.addEventListener(\"close\", onClose);\n });\n }\n\n // ─── Close ───────────────────────────────────────────────────\n\n async close(\n options: CloseOptions = {},\n ): Promise<{ code: number; reason: string }> {\n const {\n code = 1000,\n reason = \"\",\n awaitPending = true,\n force = false,\n } = options;\n\n if (this._closePromise) return this._closePromise;\n\n if (this._state === CLOSED) {\n return { code: 1000, reason: \"\" };\n }\n\n // Cancel reconnection\n if (this._reconnectTimer) {\n clearTimeout(this._reconnectTimer);\n this._reconnectTimer = null;\n }\n\n this._closePromise = this._closeInternal(code, reason, awaitPending, force);\n return this._closePromise;\n }\n\n private async _closeInternal(\n code: number,\n reason: string,\n awaitPending: boolean,\n force: boolean,\n ): Promise<{ code: number; reason: string }> {\n this._state = CLOSING;\n\n if (!force && awaitPending) {\n const pendingPromises = Array.from(this._pendingCalls.values()).map(\n (p) =>\n new Promise<void>((resolve) => {\n const origResolve = p.resolve;\n const origReject = p.reject;\n p.resolve = (v: unknown) => {\n origResolve(v);\n resolve();\n };\n p.reject = (r: unknown) => {\n origReject(r);\n resolve();\n };\n }),\n );\n if (pendingPromises.length > 0) {\n await Promise.allSettled(pendingPromises);\n }\n }\n\n return new Promise<{ code: number; reason: string }>((resolve) => {\n if (!this._ws || this._ws.readyState === WebSocket.CLOSED) {\n this._state = CLOSED;\n this._cleanup();\n const result = { code, reason };\n this.emit(\"close\", result);\n resolve(result);\n return;\n }\n\n const onClose = (event: CloseEvent) => {\n this._ws?.removeEventListener(\"close\", onClose);\n this._state = CLOSED;\n this._cleanup();\n const result = { code: event.code, reason: event.reason };\n this.emit(\"close\", result);\n resolve(result);\n };\n\n this._ws.addEventListener(\"close\", onClose);\n\n if (force) {\n // Browser WebSocket has no terminate(), close immediately\n this._ws.close();\n } else {\n // Validate close code (RFC 6455 §7.4)\n const validCode =\n code >= 1000 && code <= 4999 && ![1004, 1005, 1006].includes(code);\n this._ws.close(validCode ? code : 1000, reason);\n }\n });\n }\n\n // ─── Handlers ────────────────────────────────────────────────\n\n /**\n * Register a version-specific handler — `handle(\"ocpp1.6\", \"BootNotification\", handler)`.\n * This handler is only invoked when the active protocol matches the given version.\n */\n handle<V extends OCPPProtocol, M extends AllMethodNames<V>>(\n version: V,\n method: M,\n handler: (\n context: HandlerContext<OCPPRequestType<V, M>>,\n ) => OCPPResponseType<V, M> | Promise<OCPPResponseType<V, M>>,\n ): void;\n\n /**\n * Register a handler for the client's default protocol — `handle(\"BootNotification\", handler)`.\n * Uses the default protocol type parameter `P`.\n */\n handle<M extends AllMethodNames<P>>(\n method: M,\n handler: (\n context: HandlerContext<OCPPRequestType<P, M>>,\n ) => OCPPResponseType<P, M> | Promise<OCPPResponseType<P, M>>,\n ): void;\n\n /** Register a handler for a custom/extension method not in the typed OCPP method maps. */\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n handle(\n method: string,\n handler: (context: HandlerContext<Record<string, any>>) => any,\n ): void;\n\n /** Register a wildcard handler for all unhandled methods. */\n handle(handler: WildcardHandler): void;\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n handle(...args: any[]): void {\n if (args.length === 1 && typeof args[0] === \"function\") {\n this._wildcardHandler = args[0] as WildcardHandler;\n } else if (\n args.length === 2 &&\n typeof args[0] === \"string\" &&\n typeof args[1] === \"function\"\n ) {\n this._handlers.set(args[0], args[1] as CallHandler);\n } else if (\n args.length === 3 &&\n typeof args[0] === \"string\" &&\n typeof args[1] === \"string\" &&\n typeof args[2] === \"function\"\n ) {\n this._handlers.set(`${args[0]}:${args[1]}`, args[2] as CallHandler);\n } else {\n throw new Error(\n \"Invalid arguments: provide (version, method, handler), (method, handler), or (wildcardHandler)\",\n );\n }\n }\n\n removeHandler(method?: string): void;\n removeHandler(version: OCPPProtocol, method: string): void;\n removeHandler(versionOrMethod?: string, method?: string): void {\n if (versionOrMethod && method) {\n this._handlers.delete(`${versionOrMethod}:${method}`);\n } else if (versionOrMethod) {\n this._handlers.delete(versionOrMethod);\n } else {\n this._wildcardHandler = null;\n }\n }\n\n removeAllHandlers(): void {\n this._handlers.clear();\n this._wildcardHandler = null;\n }\n\n // ─── Middleware ──────────────────────────────────────────────\n\n /**\n * Register a middleware function to intercept calls and results.\n * Middleware executes in the order registered.\n */\n use(middleware: MiddlewareFunction<MiddlewareContext>): void {\n this._middleware.use(middleware);\n }\n\n // ─── Call ────────────────────────────────────────────────────\n\n /**\n * Call a version-specific typed method — `call(\"ocpp1.6\", \"BootNotification\", {...})`.\n * Provides full type inference for params and response based on the OCPP version.\n */\n async call<V extends OCPPProtocol, M extends AllMethodNames<V>>(\n version: V,\n method: M,\n params: OCPPRequestType<V, M>,\n options?: CallOptions,\n ): Promise<OCPPResponseType<V, M>>;\n\n /** Call a known typed method using the client's default protocol. */\n async call<M extends AllMethodNames<P>>(\n method: M,\n params: OCPPRequestType<P, M>,\n options?: CallOptions,\n ): Promise<OCPPResponseType<P, M>>;\n\n /** Call a known typed method with explicit response type. */\n async call<TResult = unknown>(\n method: string,\n params?: Record<string, unknown>,\n options?: CallOptions,\n ): Promise<TResult>;\n\n async call(...args: unknown[]): Promise<unknown> {\n let method: string;\n let params: unknown;\n let options: CallOptions;\n\n if (\n args.length >= 3 &&\n typeof args[0] === \"string\" &&\n typeof args[1] === \"string\"\n ) {\n // call(version, method, params, options?)\n method = args[1] as string;\n params = args[2] ?? {};\n options = (args[3] as CallOptions) ?? {};\n } else {\n // call(method, params?, options?)\n method = args[0] as string;\n params = args[1] ?? {};\n options = (args[2] as CallOptions) ?? {};\n }\n\n if (this._state !== OPEN) {\n throw new Error(`Cannot call: client is in state ${this._state}`);\n }\n\n return this._callQueue.push(() => this._sendCall(method, params, options));\n }\n\n private async _sendCall(\n method: string,\n params: unknown,\n options: CallOptions,\n ): Promise<unknown> {\n const msgId = this._generateMessageId();\n const timeoutMs = options.timeoutMs ?? this._options.callTimeoutMs;\n\n const ctx: MiddlewareContext = {\n type: \"outgoing_call\",\n messageId: msgId,\n method,\n params,\n options,\n };\n\n let callResult: unknown;\n\n await this._middleware.execute(ctx, async (c) => {\n const ctxvals = c as Extract<\n MiddlewareContext,\n { type: \"outgoing_call\" }\n >;\n\n const message: OCPPCall = [\n MessageType.CALL,\n msgId,\n ctxvals.method,\n ctxvals.params,\n ];\n const messageStr = JSON.stringify(message);\n\n callResult = await new Promise<unknown>((resolve, reject) => {\n const timeoutHandle = setTimeout(() => {\n this._pendingCalls.delete(msgId);\n this._logger.warn?.(\"Call timed out\", {\n messageId: msgId,\n method: ctxvals.method,\n timeoutMs,\n });\n reject(\n new TimeoutError(\n `Call to \"${ctxvals.method}\" timed out after ${timeoutMs}ms`,\n ),\n );\n }, timeoutMs);\n\n const pending: PendingCall = {\n resolve: resolve as (v: unknown) => void,\n reject,\n timeoutHandle,\n method: ctxvals.method,\n sentAt: Date.now(),\n };\n\n // Abort signal support\n if (options.signal) {\n if (options.signal.aborted) {\n clearTimeout(timeoutHandle);\n reject(options.signal.reason ?? new Error(\"Aborted\"));\n return;\n }\n const abortHandler = () => {\n clearTimeout(timeoutHandle);\n this._pendingCalls.delete(msgId);\n reject(options.signal?.reason ?? new Error(\"Aborted\"));\n };\n options.signal.addEventListener(\"abort\", abortHandler, {\n once: true,\n });\n pending.abortHandler = abortHandler;\n }\n\n this._pendingCalls.set(msgId, pending);\n this._ws?.send(messageStr);\n this.emit(\"message\", message);\n this.emit(\"call\", message);\n });\n });\n\n return callResult;\n }\n\n /**\n * Send a raw string message over the WebSocket (use with caution).\n * Messages sent while CONNECTING are buffered and flushed on open.\n */\n sendRaw(message: string): void {\n if (this._state === OPEN && this._ws) {\n this._ws.send(message);\n } else if (this._state === CONNECTING) {\n this._outboundBuffer.push(message);\n } else {\n throw new Error(\"Cannot send: client is not connected\");\n }\n }\n\n // ─── Reconfigure ─────────────────────────────────────────────\n\n reconfigure(options: Partial<BrowserClientOptions>): void {\n Object.assign(this._options, options);\n\n if (options.callConcurrency !== undefined) {\n this._callQueue.setConcurrency(options.callConcurrency);\n }\n }\n\n // ─── Internal: WebSocket attachment ──────────────────────────\n\n private _attachWebsocket(ws: WebSocket): void {\n ws.addEventListener(\"message\", (event: MessageEvent) =>\n this._onMessage(event.data),\n );\n ws.addEventListener(\"close\", (event: CloseEvent) =>\n this._onClose(event.code, event.reason),\n );\n ws.addEventListener(\"error\", (event: Event) => this.emit(\"error\", event));\n }\n\n // ─── Internal: Message handling ──────────────────────────────\n\n private _onMessage(data: unknown): void {\n const raw = typeof data === \"string\" ? data : String(data);\n\n let message: OCPPMessage;\n try {\n message = JSON.parse(raw) as OCPPMessage;\n if (!Array.isArray(message)) throw new Error(\"Message is not an array\");\n } catch (err) {\n this._onBadMessage(raw, err as Error);\n return;\n }\n\n const messageType = message[0];\n\n switch (messageType) {\n case MessageType.CALL:\n this._handleIncomingCall(message as OCPPCall);\n break;\n case MessageType.CALLRESULT:\n this._handleCallResult(message as OCPPCallResult);\n break;\n case MessageType.CALLERROR:\n this._handleCallError(message as OCPPCallError);\n break;\n default:\n this._onBadMessage(\n JSON.stringify(message),\n new RPCMessageTypeNotSupportedError(\n `Unknown message type: ${messageType}`,\n ),\n );\n }\n }\n\n private async _handleIncomingCall(message: OCPPCall): Promise<void> {\n const [, msgId, method, params] = message;\n\n const ctx: MiddlewareContext = {\n type: \"incoming_call\",\n messageId: msgId,\n method,\n params,\n protocol: this._protocol,\n };\n\n await this._middleware.execute(ctx, async (c) => {\n const ctxvals = c as Extract<\n MiddlewareContext,\n { type: \"incoming_call\" }\n >;\n\n const modifiedMessage: OCPPCall = [\n MessageType.CALL,\n ctxvals.messageId,\n ctxvals.method,\n ctxvals.params,\n ];\n this.emit(\"call\", modifiedMessage);\n\n if (this._state !== OPEN) {\n return;\n }\n\n try {\n if (this._pendingResponses.has(ctxvals.messageId)) {\n throw createRPCError(\n \"RpcFrameworkError\",\n `Already processing call with ID: ${ctxvals.messageId}`,\n );\n }\n\n const specificHandler =\n (this._protocol\n ? this._handlers.get(`${this._protocol}:${ctxvals.method}`)\n : undefined) ?? this._handlers.get(ctxvals.method);\n\n if (!specificHandler && !this._wildcardHandler) {\n throw createRPCError(\n \"NotImplemented\",\n `No handler for method: ${ctxvals.method}`,\n );\n }\n\n this._pendingResponses.add(ctxvals.messageId);\n\n const ac = new AbortController();\n const context: HandlerContext = {\n messageId: ctxvals.messageId,\n method: ctxvals.method,\n protocol: this._protocol,\n params: ctxvals.params,\n signal: ac.signal,\n };\n\n let result: unknown;\n if (specificHandler) {\n result = await specificHandler(context);\n } else if (this._wildcardHandler) {\n result = await this._wildcardHandler(ctxvals.method, context);\n }\n\n this._pendingResponses.delete(ctxvals.messageId);\n\n if (result === NOREPLY) return;\n\n const response: OCPPCallResult = [\n MessageType.CALLRESULT,\n ctxvals.messageId,\n result,\n ];\n this._ws?.send(JSON.stringify(response));\n this.emit(\"callResult\", response);\n } catch (err) {\n this._pendingResponses.delete(ctxvals.messageId);\n this._logger.error?.(\"Handler error\", {\n messageId: ctxvals.messageId,\n method: ctxvals.method,\n error: (err as Error).message,\n });\n\n const rpcErr =\n err instanceof RPCGenericError || (err as RPCError).rpcErrorCode\n ? (err as RPCError)\n : createRPCError(\"InternalError\", (err as Error).message);\n\n const details = this._options.respondWithDetailedErrors\n ? getErrorPlainObject(err as Error)\n : {};\n\n const errorResponse: OCPPCallError = [\n MessageType.CALLERROR,\n ctxvals.messageId,\n rpcErr.rpcErrorCode,\n rpcErr.rpcErrorMessage || (err as Error).message || \"\",\n details,\n ];\n this._ws?.send(JSON.stringify(errorResponse));\n this.emit(\"callError\", errorResponse);\n }\n });\n }\n\n private async _handleCallResult(message: OCPPCallResult): Promise<void> {\n const [, msgId, result] = message;\n\n if (!this._pendingCalls.has(msgId)) {\n this._logger.warn?.(\"Received CallResult for unknown messageId\", {\n messageId: msgId,\n });\n return;\n }\n\n const pending = this._pendingCalls.get(msgId)!;\n\n const ctx: MiddlewareContext = {\n type: \"incoming_result\",\n messageId: msgId,\n method: pending.method,\n payload: result,\n };\n\n await this._middleware.execute(ctx, async (c) => {\n const ctxvals = c as Extract<\n MiddlewareContext,\n { type: \"incoming_result\" }\n >;\n\n const modifiedMessage: OCPPCallResult = [\n MessageType.CALLRESULT,\n msgId,\n ctxvals.payload,\n ];\n this.emit(\"callResult\", modifiedMessage);\n\n clearTimeout(pending.timeoutHandle);\n this._pendingCalls.delete(msgId);\n pending.resolve(ctxvals.payload);\n });\n }\n\n private async _handleCallError(message: OCPPCallError): Promise<void> {\n const [, msgId, errorCode, errorMessage, errorDetails] = message;\n\n if (!this._pendingCalls.has(msgId)) {\n this._logger.warn?.(\"Received CallError for unknown messageId\", {\n messageId: msgId,\n });\n return;\n }\n\n const pending = this._pendingCalls.get(msgId)!;\n\n const error = createRPCError(errorCode, errorMessage, errorDetails);\n\n const ctx: MiddlewareContext = {\n type: \"incoming_error\",\n messageId: msgId,\n method: pending.method,\n error: error as unknown as OCPPCallError, // Map to types.ts expected `error` shape which takes OCPPCallError specifically here, though we pass it via RPCError\n };\n\n await this._middleware.execute(ctx, async (c) => {\n const ctxvals = c as Extract<\n MiddlewareContext,\n { type: \"incoming_error\" }\n >;\n\n // Cast back to any to extract dynamic properties cleanly\n const resolvedRpcErr = ctxvals.error as unknown as any;\n\n const modifiedMessage: OCPPCallError = [\n MessageType.CALLERROR,\n msgId,\n resolvedRpcErr.rpcErrorCode,\n resolvedRpcErr.message,\n resolvedRpcErr.rpcErrorDetails ?? {},\n ];\n this.emit(\"callError\", modifiedMessage);\n\n clearTimeout(pending.timeoutHandle);\n this._pendingCalls.delete(msgId);\n pending.reject(resolvedRpcErr);\n });\n }\n\n // ─── Internal: Bad message handling ──────────────────────────\n\n private _onBadMessage(rawMessage: string, error: Error): void {\n this._badMessageCount++;\n this._logger?.warn?.(\"Bad message\", {\n error: error.message,\n count: this._badMessageCount,\n });\n this.emit(\"badMessage\", { message: rawMessage, error });\n\n // Best-effort: try to extract messageId and respond with CALLERROR\n const match = rawMessage.match(/^\\s*\\[\\s*2\\s*,\\s*\"([^\"]+)\"/);\n if (match?.[1] && this._ws) {\n const errorResponse: OCPPCallError = [\n MessageType.CALLERROR,\n match[1],\n \"FormatViolation\",\n error.message || \"Invalid message format\",\n {},\n ];\n this._ws.send(JSON.stringify(errorResponse));\n this.emit(\"callError\", errorResponse);\n }\n\n if (this._badMessageCount >= this._options.maxBadMessages) {\n this.close({ code: 1002, reason: \"Too many bad messages\" }).catch(\n () => {},\n );\n }\n }\n\n // ─── Internal: Close handling ────────────────────────────────\n\n /**\n * Reject all in-flight calls and clear pending state.\n */\n private _rejectPendingCalls(reason: string): void {\n for (const [, pending] of this._pendingCalls) {\n clearTimeout(pending.timeoutHandle);\n pending.reject(new Error(reason));\n }\n this._pendingCalls.clear();\n this._pendingResponses.clear();\n }\n\n private _onClose(code: number, reason: string): void {\n this._rejectPendingCalls(`Connection closed (${code}: ${reason})`);\n\n if (this._state !== CLOSING) {\n // Unexpected close — emit disconnect (transient, reconnect may follow)\n this._logger?.info?.(\"Disconnected\", { code, reason });\n this.emit(\"disconnect\", { code, reason });\n\n if (\n this._options.reconnect &&\n this._reconnectAttempt < this._options.maxReconnects\n ) {\n this._scheduleReconnect();\n } else {\n // No reconnect — permanent close\n this._state = CLOSED;\n this.emit(\"close\", { code, reason });\n }\n } else {\n this._state = CLOSED;\n // close() handles the emit\n }\n }\n\n // ─── Internal: Reconnection ──────────────────────────────────\n\n /** Errors that should stop reconnection immediately */\n private static readonly _INTOLERABLE_ERRORS = new Set([\n \"Maximum redirects exceeded\",\n \"Server sent no subprotocol\",\n \"Server sent an invalid subprotocol\",\n \"Server sent a subprotocol but none was requested\",\n \"Invalid Sec-WebSocket-Accept header\",\n ]);\n\n private _scheduleReconnect(): void {\n this._reconnectAttempt++;\n this._state = CONNECTING;\n\n // Exponential backoff with jitter (OCPP 2.0.1 §J.1)\n const base = this._options.backoffMin;\n const max = this._options.backoffMax;\n const delayMs = Math.min(\n max,\n base * 2 ** (this._reconnectAttempt - 1) * (0.5 + Math.random() * 0.5),\n );\n\n this._logger?.warn?.(\"Reconnecting\", {\n attempt: this._reconnectAttempt,\n delayMs: Math.round(delayMs),\n });\n this.emit(\"reconnect\", { attempt: this._reconnectAttempt, delay: delayMs });\n\n this._reconnectTimer = setTimeout(async () => {\n this._reconnectTimer = null;\n try {\n await this._connectInternal();\n } catch (err) {\n // Intolerable errors — do not retry\n const msg = err instanceof Error ? err.message : \"\";\n if (BrowserOCPPClient._INTOLERABLE_ERRORS.has(msg)) {\n this._logger?.error?.(\"Intolerable error — stopping reconnection\", {\n error: msg,\n });\n this._state = CLOSED;\n this.emit(\"close\", { code: 1001, reason: msg });\n return;\n }\n\n if (\n this._reconnectAttempt < this._options.maxReconnects &&\n this._options.reconnect\n ) {\n this._scheduleReconnect();\n } else {\n // Max reconnects exhausted\n this._state = CLOSED;\n this.emit(\"close\", {\n code: 1001,\n reason: \"Max reconnection attempts exhausted\",\n });\n }\n }\n }, delayMs);\n }\n\n // ─── Internal: Endpoint building ─────────────────────────────\n\n private _buildEndpoint(): string {\n let url = this._options.endpoint;\n\n if (!url.endsWith(\"/\")) url += \"/\";\n url += encodeURIComponent(this._identity);\n\n if (this._options.query) {\n const params = new URLSearchParams(this._options.query);\n url += (url.includes(\"?\") ? \"&\" : \"?\") + params.toString();\n }\n\n return url;\n }\n\n // ─── Internal: Cleanup ───────────────────────────────────────\n\n private _cleanup(): void {\n this._closePromise = null;\n this._ws = null;\n }\n\n // ─── Internal: ID Generation ─────────────────────────────────\n\n private _generateMessageId(): string {\n // 1. Try native crypto.randomUUID (Fastest, secure, requires HTTPS/localhost)\n if (\n typeof crypto !== \"undefined\" &&\n typeof crypto.randomUUID === \"function\"\n ) {\n return crypto.randomUUID();\n }\n\n // 2. Fallback to Math.random() for older browsers or insecure HTTP contexts\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACgBO,SAAS,iBACd,IACsB;AACtB,SAAO;AACT;AAOO,SAAS,oBACd,IAC8B;AAC9B,SAAO;AACT;AAQO,SAAS,WACd,IACwB;AACxB,SAAO;AACT;AAUO,SAAS,eAAe,KAAmC;AAChE,SAAO,OAAO,QAAQ;AACpB,QAAI,WAAW;AACf,QAAI,WAAW;AAGf,UAAM,gBAAgB,CAAC,SAA2B;AAChD,iBAAW;AACX,UAAI,OAAO,IAAI;AAAA,IACjB;AAEA,UAAM,gBAAgB,CAAC,MAAe,YAA4B;AAChE,iBAAW;AACX,aAAO,IAAI,OAAO,MAAM,OAAO;AAAA,IACjC;AAEA,UAAM,aAAgD;AAAA,MACpD,GAAG;AAAA,MACH,QAAQ;AAAA,MACR,QAAQ;AAAA,IACV;AAEA,QAAI;AACF,iBAAW,MAAM,KAAK;AACpB,YAAI,IAAI,OAAO,WAAW,YAAY,SAAU;AAGhD,cAAM,IAAI,GAAG,UAAU;AACvB,YAAI,aAAa,SAAS;AACxB,gBAAM;AAAA,QACR;AAEA,YAAI,YAAY,SAAU;AAAA,MAC5B;AAGA,UAAI,CAAC,YAAY,CAAC,UAAU;AAC1B;AAAA,UACE;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF,SAAS,MAAM;AACb,UAAI,CAAC,UAAU;AACb;AAAA,UACE;AAAA,UACA;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAAA,EACF;AACF;AAQO,SAAS,wBACd,QACA,UACA,SAAkC,CAAC,GACS;AAC5C,QAAM,UAAU,OAAO,WAAW,WAAW,SAAS,CAAC;AACvD,QAAM,EAAE,cAAc,OAAO,WAAW,MAAM,IAAI;AAElD,SAAO,OAAO,KAAK,SAAS;AAC1B,UAAM,QAAQ,KAAK,IAAI;AACvB,UAAM,SAAS,IAAI;AAGnB,UAAM,QAAQ,cAAc,SAAS;AAErC,YAAQ,IAAI,MAAM;AAAA,MAChB,KAAK;AACH,YAAI,eAAe,UAAU;AAC3B,iBAAO,KAAK,IAAI,UAAK,QAAQ,aAAQ,MAAM,UAAU;AAAA,YACnD,WAAW,IAAI;AAAA,YACf,QAAQ,IAAI;AAAA,YACZ,UAAU,IAAI;AAAA,YACd,SAAS,IAAI;AAAA,YACb,WAAW;AAAA,UACb,CAAC;AAAA,QACH,OAAO;AACL,iBAAO,KAAK,IAAI,eAAU;AAAA,YACxB,WAAW,IAAI;AAAA,YACf,QAAQ,IAAI;AAAA,YACZ,UAAU,IAAI;AAAA,YACd,SAAS,IAAI;AAAA,YACb,WAAW;AAAA,UACb,CAAC;AAAA,QACH;AACA;AAAA,MAEF,KAAK;AACH,YAAI,eAAe,UAAU;AAC3B,iBAAO,KAAK,IAAI,UAAK,QAAQ,aAAQ,MAAM,WAAW;AAAA,YACpD,QAAQ,IAAI;AAAA,YACZ,QAAQ,IAAI;AAAA,YACZ,WAAW;AAAA,UACb,CAAC;AAAA,QACH,OAAO;AACL,iBAAO,KAAK,IAAI,eAAU;AAAA,YACxB,QAAQ,IAAI;AAAA,YACZ,QAAQ,IAAI;AAAA,YACZ,WAAW;AAAA,UACb,CAAC;AAAA,QACH;AACA;AAAA,IACJ;AAEA,QAAI;AACF,YAAM,SAAS,MAAM,KAAK;AAC1B,YAAM,aAAa,KAAK,IAAI,IAAI;AAEhC,cAAQ,IAAI,MAAM;AAAA,QAChB,KAAK;AACH,cAAI,WAAW,UAAa,WAAW,MAAM;AAC3C,gBAAI,eAAe,UAAU;AAC3B,qBAAO,KAAK,IAAI,UAAK,QAAQ,aAAQ,MAAM,WAAW;AAAA,gBACpD,WAAW,IAAI;AAAA,gBACf,QAAQ,IAAI;AAAA,gBACZ;AAAA,gBACA,QAAQ;AAAA,gBACR,WAAW;AAAA,cACb,CAAC;AAAA,YACH,OAAO;AACL,qBAAO,KAAK,IAAI,qBAAgB;AAAA,gBAC9B,WAAW,IAAI;AAAA,gBACf,QAAQ,IAAI;AAAA,gBACZ;AAAA,gBACA,QAAQ;AAAA,gBACR,WAAW;AAAA,cACb,CAAC;AAAA,YACH;AAAA,UACF;AACA;AAAA,QAEF,KAAK;AACH,cAAI,eAAe,UAAU;AAC3B,mBAAO,KAAK,IAAI,UAAK,QAAQ,aAAQ,MAAM,WAAW;AAAA,cACpD,WAAY,IAAY;AAAA,cACxB,QAAQ,IAAI;AAAA,cACZ;AAAA,cACA,SAAS;AAAA,cACT,WAAW;AAAA,YACb,CAAC;AAAA,UACH,OAAO;AACL,mBAAO,KAAK,IAAI,qBAAgB;AAAA,cAC9B,WAAY,IAAY;AAAA,cACxB,QAAQ,IAAI;AAAA,cACZ;AAAA,cACA,SAAS;AAAA,cACT,WAAW;AAAA,YACb,CAAC;AAAA,UACH;AACA;AAAA,MACJ;AAEA,aAAO;AAAA,IACT,SAAS,KAAK;AACZ,YAAM,MAAO,IAAc;AAC3B,YAAM,aAAa,KAAK,IAAI,IAAI;AAEhC,UAAI,IAAI,SAAS,iBAAiB;AAChC,YAAI,eAAe,UAAU;AAC3B,iBAAO,QAAQ,aAAM,QAAQ,aAAQ,MAAM,WAAW;AAAA,YACpD,WAAW,IAAI;AAAA,YACf,QAAQ,IAAI;AAAA,YACZ;AAAA,YACA,OAAO;AAAA,YACP,WAAW;AAAA,UACb,CAAC;AAAA,QACH,OAAO;AACL,iBAAO,QAAQ,oBAAe;AAAA,YAC5B,WAAW,IAAI;AAAA,YACf,QAAQ,IAAI;AAAA,YACZ;AAAA,YACA,OAAO;AAAA,YACP,WAAW;AAAA,UACb,CAAC;AAAA,QACH;AAAA,MACF,WAAW,IAAI,SAAS,iBAAiB;AACvC,YAAI,eAAe,UAAU;AAC3B,iBAAO,OAAO,aAAM,QAAQ,aAAQ,MAAM,WAAW;AAAA,YACnD,WAAY,IAAY;AAAA,YACxB,QAAQ,IAAI;AAAA,YACZ;AAAA,YACA,OAAO;AAAA,YACP,WAAW;AAAA,UACb,CAAC;AAAA,QACH,OAAO;AACL,iBAAO,OAAO,oBAAe;AAAA,YAC3B,WAAY,IAAY;AAAA,YACxB,QAAQ,IAAI;AAAA,YACZ;AAAA,YACA,OAAO;AAAA,YACP,WAAW;AAAA,UACb,CAAC;AAAA,QACH;AAAA,MACF;AACA,YAAM;AAAA,IACR;AAAA,EACF;AACF;;;ACpPO,IAAM,kBAAN,MAAgC;AAAA;AAAA,EAE7B,SAA8C,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,EAMvD,IAAmB,YAAyD;AAC1E,SAAK,OAAO,KAAK,UAAU;AAAA,EAC7B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,QACJ,SACA,QACkB;AAClB,QAAI,QAAQ;AAEZ,UAAM,WAAW,OAAO,MAAgC;AACtD,UAAI,KAAK,OAAO;AACd,cAAM,IAAI,MAAM,8BAA8B;AAAA,MAChD;AACA,cAAQ;AAER,YAAM,KAAK,KAAK,OAAO,CAAC;AAExB,UAAI,MAAM,KAAK,OAAO,QAAQ;AAC5B,eAAO,OAAO,OAAO;AAAA,MACvB;AAEA,UAAI,CAAC,IAAI;AACP,eAAO;AAAA,MACT;AAEA,aAAO,GAAG,SAAS,MAAM,SAAS,IAAI,CAAC,CAAC;AAAA,IAC1C;AAEA,WAAO,SAAS,CAAC;AAAA,EACnB;AACF;;;ACnDA,wBAOO;AAQP,SAAS,wBAAwB,QAAgC;AAC/D,SACE,OAAO,iBAAiB,SACxB,OAAO,mBAAmB,SAC1B,OAAO,mBAAmB,QAC1B,OAAO,qBAAqB;AAEhC;AAUA,SAAS,uBAAuB,QAAsC;AACpE,QAAM,WAAW,OAAO,gBAAgB;AACxC,QAAM,aAAa,OAAO,kBAAkB;AAC5C,QAAM,YAAY,OAAO,kBAAkB;AAC3C,QAAM,aAAa,OAAO,oBAAoB;AAG9C,QAAM,MAAM;AACZ,QAAM,QAAQ;AACd,QAAM,OAAO;AAEb,SAAO,CAAC,OAAiB,SAAgC;AAEvD,QAAI,CAAC,YAAY;AAEf,YAAM,UAAU;AAAA,IAClB,WAAW,aAAa,MAAM,SAAS;AAErC,YAAM,QAAkB,CAAC;AACzB,UAAI,MAAM,QAAQ,UAAW,OAAM,KAAK,OAAO,MAAM,QAAQ,SAAS,CAAC;AACvE,UAAI,MAAM,QAAQ,SAAU,OAAM,KAAK,OAAO,MAAM,QAAQ,QAAQ,CAAC;AACrE,UAAI,MAAM,SAAS,GAAG;AAEpB,cAAM,UAAU,GAAG,GAAG,IAAI,MAAM,KAAK,GAAG,CAAC,IAAI,KAAK,IAAI,MAAM,OAAO;AACnE,cAAM,UAAU;AAAA,MAClB;AAAA,IACF;AAGA,UAAM,OAAO,MAAM;AACnB,QAAI,CAAC,UAAU;AAEb,YAAM,OAAO,CAAC;AAAA,IAChB,WAAW,cAAc,QAAQ,OAAO,KAAK,IAAI,EAAE,SAAS,GAAG;AAE7D,YAAM,QAAQ,OAAO,QAAQ,IAAI,EAC9B,OAAO,CAAC,CAAC,EAAE,CAAC,MAAM,MAAM,UAAa,MAAM,IAAI,EAC/C,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM;AACf,YAAI,SAAS,OAAO,MAAM,WAAW,KAAK,UAAU,CAAC,IAAI,OAAO,CAAC;AAEjE,YAAI,OAAO,MAAM,UAAU;AACzB,mBAAS,GAAG,GAAG,GAAG,MAAM,GAAG,KAAK;AAAA,QAClC,OAAO;AACL,mBAAS,GAAG,GAAG,GAAG,MAAM,GAAG,KAAK;AAAA,QAClC;AACA,eAAO,GAAG,IAAI,GAAG,CAAC,GAAG,KAAK,IAAI,MAAM;AAAA,MACtC,CAAC,EACA,KAAK,GAAG;AACX,UAAI,OAAO;AACT,cAAM,UAAU,GAAG,MAAM,OAAO,KAAK,KAAK;AAAA,MAC5C;AACA,YAAM,OAAO,CAAC;AAAA,IAChB;AAEA,SAAK,KAAK;AAAA,EACZ;AACF;AAOO,SAAS,WACd,QACA,gBACmB;AAEnB,MAAI,WAAW,MAAO,QAAO;AAC7B,MAAI,QAAQ,YAAY,MAAO,QAAO;AAGtC,MAAI,QAAQ,QAAQ;AAClB,QAAI,kBAAkB,OAAO,OAAO,OAAO;AACzC,aAAO,OAAO,OAAO,MAAM,cAAc;AAAA,IAC3C;AACA,WAAO,OAAO;AAAA,EAChB;AAGA,QAAM,QAAS,QAAQ,SAAS;AAChC,QAAM,cAAc,QAAQ,YAAY;AAExC,QAAM,aAAa,cACf,KAAC,mCAAgB,EAAE,MAAM,CAAC,CAAC,IAC3B,KAAC,oCAAiB,EAAE,MAAM,CAAC,CAAC;AAEhC,MAAI,QAAQ,SAAS;AACnB,UAAM,kBAAkB,OAAO;AAC/B,eAAW,KAAK;AAAA,MACd,MAAM;AAAA,MACN,OAAO,CAAC,UAAU,gBAAgB,KAAK;AAAA,IACzC,CAAC;AAAA,EACH;AAGA,QAAM,aAA8B,CAAC;AACrC,MAAI,UAAU,wBAAwB,MAAM,GAAG;AAC7C,eAAW,KAAK,uBAAuB,MAAM,CAAC;AAAA,EAChD;AAEA,QAAM,aAAS,gCAAa;AAAA,IAC1B;AAAA,IACA;AAAA,IACA,YAAY,WAAW,SAAS,IAAI,aAAa;AAAA,EACnD,CAAC;AAGD,MAAI,kBAAkB,OAAO,KAAK,cAAc,EAAE,SAAS,GAAG;AAC5D,WAAO,OAAO,MAAM,cAAc;AAAA,EACpC;AAEA,SAAO;AACT;;;ACjJO,IAAM,eAAN,MAAmB;AAAA,EAChB,aAAa,oBAAI,IAAwB;AAAA,EAEjD,GAAG,OAAe,UAA0B;AAC1C,UAAM,MAAM,KAAK,WAAW,IAAI,KAAK;AACrC,QAAI,KAAK;AACP,UAAI,KAAK,QAAQ;AAAA,IACnB,OAAO;AACL,WAAK,WAAW,IAAI,OAAO,CAAC,QAAQ,CAAC;AAAA,IACvC;AACA,WAAO;AAAA,EACT;AAAA,EAEA,KAAK,OAAe,UAA0B;AAC5C,UAAM,UAAoB,IAAI,SAAS;AACrC,WAAK,IAAI,OAAO,OAAO;AACvB,eAAS,GAAG,IAAI;AAAA,IAClB;AAEA,IAAC,QAAgB,YAAY;AAC7B,WAAO,KAAK,GAAG,OAAO,OAAO;AAAA,EAC/B;AAAA,EAEA,IAAI,OAAe,UAA0B;AAC3C,UAAM,MAAM,KAAK,WAAW,IAAI,KAAK;AACrC,QAAI,CAAC,IAAK,QAAO;AACjB,UAAM,MAAM,IAAI;AAAA;AAAA,MAEd,CAAC,OAAO,OAAO,YAAa,GAAW,cAAc;AAAA,IACvD;AACA,QAAI,QAAQ,GAAI,KAAI,OAAO,KAAK,CAAC;AACjC,QAAI,IAAI,WAAW,EAAG,MAAK,WAAW,OAAO,KAAK;AAClD,WAAO;AAAA,EACT;AAAA,EAEA,KAAK,UAAkB,MAA0B;AAC/C,UAAM,MAAM,KAAK,WAAW,IAAI,KAAK;AACrC,QAAI,CAAC,OAAO,IAAI,WAAW,EAAG,QAAO;AACrC,eAAW,MAAM,CAAC,GAAG,GAAG,GAAG;AACzB,SAAG,GAAG,IAAI;AAAA,IACZ;AACA,WAAO;AAAA,EACT;AAAA,EAEA,YAAY,OAAe,UAA0B;AACnD,WAAO,KAAK,GAAG,OAAO,QAAQ;AAAA,EAChC;AAAA,EAEA,eAAe,OAAe,UAA0B;AACtD,WAAO,KAAK,IAAI,OAAO,QAAQ;AAAA,EACjC;AAAA,EAEA,mBAAmB,OAAsB;AACvC,QAAI,OAAO;AACT,WAAK,WAAW,OAAO,KAAK;AAAA,IAC9B,OAAO;AACL,WAAK,WAAW,MAAM;AAAA,IACxB;AACA,WAAO;AAAA,EACT;AAAA,EAEA,cAAc,OAAuB;AACnC,WAAO,KAAK,WAAW,IAAI,KAAK,GAAG,UAAU;AAAA,EAC/C;AACF;;;ACtEO,IAAM,eAAN,cAA2B,MAAM;AAAA,EACtC,YAAY,UAAU,uBAAuB;AAC3C,UAAM,OAAO;AACb,SAAK,OAAO;AAAA,EACd;AACF;AAUO,IAAM,kBAAN,cAA8B,MAA0B;AAAA,EACpD,eAAuB;AAAA,EACvB,kBAA0B;AAAA,EAC1B;AAAA,EAET,YAAY,SAAkB,UAAmC,CAAC,GAAG;AACnE,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,UAAU;AAAA,EACjB;AACF;AAIO,IAAM,yBAAN,cAAqC,gBAAgB;AAAA,EACxC,eAAe;AAAA,EACf,kBAAkB;AAAA,EAEpC,YAAY,SAAkB,UAAmC,CAAC,GAAG;AACnE,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,uBAAN,cAAmC,gBAAgB;AAAA,EACtC,eAAe;AAAA,EACf,kBAChB;AAAA,EAEF,YAAY,SAAkB,UAAmC,CAAC,GAAG;AACnE,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,mBAAN,cAA+B,gBAAgB;AAAA,EAClC,eAAe;AAAA,EACf,kBAChB;AAAA,EAEF,YAAY,SAAkB,UAAmC,CAAC,GAAG;AACnE,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,mBAAN,cAA+B,gBAAgB;AAAA,EAClC,eAAe;AAAA,EACf,kBAAkB;AAAA,EAEpC,YAAY,SAAkB,UAAmC,CAAC,GAAG;AACnE,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,mBAAN,cAA+B,gBAAgB;AAAA,EAClC,eAAe;AAAA,EACf,kBAChB;AAAA,EAEF,YAAY,SAAkB,UAAmC,CAAC,GAAG;AACnE,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,6BAAN,cAAyC,gBAAgB;AAAA,EAC5C,eAAe;AAAA,EACf,kBAChB;AAAA,EAEF,YAAY,SAAkB,UAAmC,CAAC,GAAG;AACnE,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,0BAAN,cAAsC,gBAAgB;AAAA,EACzC,eAAe;AAAA,EACf,kBAChB;AAAA,EAEF,YAAY,SAAkB,UAAmC,CAAC,GAAG;AACnE,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,sCAAN,cAAkD,gBAAgB;AAAA,EACrD,eAAe;AAAA,EACf,kBAChB;AAAA,EAEF,YAAY,SAAkB,UAAmC,CAAC,GAAG;AACnE,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,wCAAN,cAAoD,gBAAgB;AAAA,EACvD,eAAe;AAAA,EACf,kBAChB;AAAA,EAEF,YAAY,SAAkB,UAAmC,CAAC,GAAG;AACnE,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,kCAAN,cAA8C,gBAAgB;AAAA,EACjD,eAAe;AAAA,EACf,kBAChB;AAAA,EAEF,YAAY,SAAkB,UAAmC,CAAC,GAAG;AACnE,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,kCAAN,cAA8C,gBAAgB;AAAA,EACjD,eAAe;AAAA,EACf,kBAChB;AAAA,EAEF,YAAY,SAAkB,UAAmC,CAAC,GAAG;AACnE,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;AAEO,IAAM,oBAAN,cAAgC,gBAAgB;AAAA,EACnC,eAAe;AAAA,EACf,kBAChB;AAAA,EAEF,YAAY,SAAkB,UAAmC,CAAC,GAAG;AACnE,UAAM,SAAS,OAAO;AACtB,SAAK,OAAO;AAAA,EACd;AACF;;;AC3JO,IAAM,QAAN,MAAY;AAAA,EACT;AAAA,EACA,WAAW;AAAA,EACX,SAIH,CAAC;AAAA,EAEN,YAAY,cAAc,GAAG;AAC3B,SAAK,eAAe,KAAK,IAAI,GAAG,WAAW;AAAA,EAC7C;AAAA,EAEA,IAAI,cAAsB;AACxB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,UAAkB;AACpB,WAAO,KAAK,OAAO;AAAA,EACrB;AAAA,EAEA,IAAI,UAAkB;AACpB,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,IAAI,OAAe;AACjB,WAAO,KAAK,WAAW,KAAK,OAAO;AAAA,EACrC;AAAA,EAEA,eAAe,aAA2B;AACxC,SAAK,eAAe,KAAK,IAAI,GAAG,WAAW;AAC3C,SAAK,OAAO;AAAA,EACd;AAAA,EAEA,KAAQ,IAAkC;AACxC,WAAO,IAAI,QAAW,CAAC,SAAS,WAAW;AACzC,WAAK,OAAO,KAAK;AAAA,QACf;AAAA,QACA;AAAA,QACA;AAAA,MACF,CAAC;AACD,WAAK,OAAO;AAAA,IACd,CAAC;AAAA,EACH;AAAA,EAEQ,SAAe;AACrB,WAAO,KAAK,WAAW,KAAK,gBAAgB,KAAK,OAAO,SAAS,GAAG;AAClE,YAAM,OAAO,KAAK,OAAO,MAAM;AAC/B,WAAK;AAEL,YACI,GAAG,EACJ,KAAK,KAAK,OAAO,EACjB,MAAM,KAAK,MAAM,EACjB,QAAQ,MAAM;AACb,aAAK;AACL,aAAK,OAAO;AAAA,MACd,CAAC;AAAA,IACL;AAAA,EACF;AACF;;;ACuBO,IAAM,kBAAkB;AAAA,EAC7B,YAAY;AAAA,EACZ,MAAM;AAAA,EACN,SAAS;AAAA,EACT,QAAQ;AACV;AAoBO,IAAM,cAAc;AAAA,EACzB,MAAM;AAAA,EACN,YAAY;AAAA,EACZ,WAAW;AACb;AAslBO,IAAM,UAAyB,uBAAO,SAAS;;;AC1kB/C,IAAM,cAAqC;AAAA,EAChD,OAAO,MAAM;AAAA,EAAC;AAAA,EACd,MAAM,MAAM;AAAA,EAAC;AAAA,EACb,MAAM,MAAM;AAAA,EAAC;AAAA,EACb,OAAO,MAAM;AAAA,EAAC;AAAA,EACd,OAAO,MAAM;AACf;;;AC/HA,IAAM,qBAAqB,oBAAI,IAM7B;AAAA,EACA,CAAC,gBAAuB,eAAe;AAAA,EACvC,CAAC,qBAA4B,iBAAiB;AAAA,EAC9C,CAAC,2BAAkC,+BAA+B;AAAA,EAClE,CAAC,kBAAyB,sBAAsB;AAAA,EAChD,CAAC,gBAAuB,oBAAoB;AAAA,EAC5C,CAAC,iBAAwB,gBAAgB;AAAA,EACzC,CAAC,iBAAwB,gBAAgB;AAAA,EACzC,CAAC,iBAAwB,gBAAgB;AAAA,EACzC,CAAC,mBAA0B,uBAAuB;AAAA,EAClD,CAAC,sBAA6B,0BAA0B;AAAA,EACxD,CAAC,+BAAsC,mCAAmC;AAAA,EAC1E;AAAA,IACE;AAAA,IACO;AAAA,EACT;AAAA,EACA,CAAC,2BAAkC,+BAA+B;AACpE,CAAC;AAMM,SAAS,eACd,MACA,SACA,UAAmC,CAAC,GAC1B;AACV,QAAM,OAAO,mBAAmB,IAAI,IAAI,KAAY;AACpD,SAAO,IAAI,KAAK,SAAS,OAAO;AAClC;AAIA,IAAM,mBAAmB;AAAA,EACvB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAKO,SAAS,oBAAoB,KAAqC;AACvE,QAAM,SAAkC,CAAC;AAEzC,aAAW,QAAQ,kBAAkB;AACnC,UAAM,QAAS,IAA2C,IAAI;AAC9D,QAAI,UAAU,QAAW;AACvB,UAAI,OAAO,UAAU,cAAc,OAAO,UAAU,SAAU;AAE9D,UAAI,OAAO,UAAU,YAAY,UAAU,MAAM;AAC/C,YAAI;AACF,eAAK,UAAU,KAAK;AACpB,iBAAO,IAAI,IAAI;AAAA,QACjB,QAAQ;AAAA,QAER;AAAA,MACF,OAAO;AACL,eAAO,IAAI,IAAI;AAAA,MACjB;AAAA,IACF;AAAA,EACF;AAEA,MAAI,CAAC,OAAO,KAAM,QAAO,OAAO,IAAI;AACpC,MAAI,CAAC,OAAO,QAAS,QAAO,UAAU,IAAI;AAE1C,SAAO;AACT;;;ACrCA,IAAM,EAAE,YAAY,MAAM,SAAS,OAAO,IAAI;AA+BvC,IAAM,oBAAN,MAAM,2BAEH,aAAa;AAAA;AAAA,EAErB,OAAgB,aAAa;AAAA,EAC7B,OAAgB,OAAO;AAAA,EACvB,OAAgB,UAAU;AAAA,EAC1B,OAAgB,SAAS;AAAA,EAEjB;AAAA,EAiBA,SACN;AAAA,EACM,MAAwB;AAAA,EACxB;AAAA,EACA;AAAA,EAEA,YAAY,oBAAI,IAAyB;AAAA,EACzC,mBAA2C;AAAA,EAC3C,gBAAgB,oBAAI,IAAyB;AAAA,EAC7C,oBAAoB,oBAAI,IAAY;AAAA,EACpC;AAAA,EACA,gBACN;AAAA,EACM,oBAAoB;AAAA,EACpB,kBAAwD;AAAA,EACxD,mBAAmB;AAAA,EACnB,kBAA4B,CAAC;AAAA,EAC7B;AAAA,EACA;AAAA,EAER,YAAY,SAA+B;AACzC,UAAM;AAEN,QAAI,CAAC,QAAQ,UAAU;AACrB,YAAM,IAAI,MAAM,sBAAsB;AAAA,IACxC;AAEA,SAAK,YAAY,QAAQ;AAEzB,SAAK,WAAW;AAAA,MACd,WAAW;AAAA,MACX,eAAe;AAAA,MACf,YAAY;AAAA,MACZ,YAAY;AAAA,MACZ,eAAe;AAAA,MACf,iBAAiB;AAAA,MACjB,gBAAgB;AAAA,MAChB,2BAA2B;AAAA,MAC3B,GAAG;AAAA,IACL;AAEA,SAAK,aAAa,IAAI,MAAM,KAAK,SAAS,eAAe;AACzD,SAAK,cAAc,IAAI,gBAAmC;AAG1D,UAAM,iBAAiB,WAAW,KAAK,SAAS,SAAS;AAAA,MACvD,WAAW;AAAA,MACX,UAAU,KAAK;AAAA,IACjB,CAAC;AACD,SAAK,UAAU,kBAAkB;AAAA,EACnC;AAAA;AAAA,EAIA,IAAI,MAA6B;AAC/B,WAAO,KAAK;AAAA,EACd;AAAA,EACA,IAAI,WAAmB;AACrB,WAAO,KAAK;AAAA,EACd;AAAA,EACA,IAAI,WAA+B;AACjC,WAAO,KAAK;AAAA,EACd;AAAA,EACA,IAAI,QAAgE;AAClE,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAIA,MAAM,UAAyB;AAC7B,QAAI,KAAK,WAAW,QAAQ;AAC1B,YAAM,IAAI,MAAM,sCAAsC,KAAK,MAAM,EAAE;AAAA,IACrE;AAEA,SAAK,SAAS;AACd,SAAK,oBAAoB;AAEzB,WAAO,KAAK,iBAAiB;AAAA,EAC/B;AAAA,EAEA,MAAc,mBAAkC;AAC9C,WAAO,IAAI,QAAc,CAAC,SAAS,WAAW;AAC5C,YAAM,WAAW,KAAK,eAAe;AAErC,WAAK,QAAQ,QAAQ,cAAc,EAAE,KAAK,SAAS,CAAC;AACpD,WAAK,KAAK,cAAc,EAAE,KAAK,SAAS,CAAC;AAEzC,UAAI;AACJ,UAAI;AACF,aAAK,KAAK,SAAS,WAAW,SAC1B,IAAI,UAAU,UAAU,KAAK,SAAS,SAAS,IAC/C,IAAI,UAAU,QAAQ;AAAA,MAC5B,SAAS,KAAK;AACZ,aAAK,SAAS;AACd,eAAO,GAAG;AACV;AAAA,MACF;AACA,WAAK,MAAM;AAEX,YAAM,SAAS,CAAC,UAAiB;AAC/B,gBAAQ;AACR,aAAK,SAAS;AACd,aAAK,YAAY,GAAG,YAAY;AAChC,aAAK,mBAAmB;AAGxB,YAAI,GAAG,YAAY,KAAK,sBAAsB,GAAG;AAC/C,eAAK,SAAS,YAAY,CAAC,GAAG,QAAQ;AAAA,QACxC;AAEA,aAAK,iBAAiB,EAAE;AAGxB,YAAI,KAAK,gBAAgB,SAAS,GAAG;AACnC,gBAAM,SAAS,KAAK;AACpB,eAAK,kBAAkB,CAAC;AACxB,qBAAW,OAAO,OAAQ,MAAK,KAAK,KAAK,GAAG;AAAA,QAC9C;AAEA,aAAK,QAAQ,OAAO,aAAa;AAAA,UAC/B,UAAU,GAAG,YAAY;AAAA,QAC3B,CAAC;AACD,aAAK,KAAK,QAAQ,KAAK;AACvB,gBAAQ;AAAA,MACV;AAEA,YAAM,UAAU,CAAC,UAAiB;AAChC,gBAAQ;AACR,aAAK,SAAS;AACd,aAAK,QAAQ,QAAQ,kBAAkB;AACvC,aAAK,KAAK,SAAS,KAAK;AACxB,eAAO,KAAK;AAAA,MACd;AAEA,YAAM,UAAU,MAAM;AACpB,gBAAQ;AACR,YAAI,KAAK,WAAW,YAAY;AAC9B,eAAK,SAAS;AACd,iBAAO,IAAI,MAAM,oCAAoC,CAAC;AAAA,QACxD;AAAA,MACF;AAEA,YAAM,UAAU,MAAM;AACpB,WAAG,oBAAoB,QAAQ,MAAM;AACrC,WAAG,oBAAoB,SAAS,OAAO;AACvC,WAAG,oBAAoB,SAAS,OAAO;AAAA,MACzC;AAEA,SAAG,iBAAiB,QAAQ,MAAM;AAClC,SAAG,iBAAiB,SAAS,OAAO;AACpC,SAAG,iBAAiB,SAAS,OAAO;AAAA,IACtC,CAAC;AAAA,EACH;AAAA;AAAA,EAIA,MAAM,MACJ,UAAwB,CAAC,GACkB;AAC3C,UAAM;AAAA,MACJ,OAAO;AAAA,MACP,SAAS;AAAA,MACT,eAAe;AAAA,MACf,QAAQ;AAAA,IACV,IAAI;AAEJ,QAAI,KAAK,cAAe,QAAO,KAAK;AAEpC,QAAI,KAAK,WAAW,QAAQ;AAC1B,aAAO,EAAE,MAAM,KAAM,QAAQ,GAAG;AAAA,IAClC;AAGA,QAAI,KAAK,iBAAiB;AACxB,mBAAa,KAAK,eAAe;AACjC,WAAK,kBAAkB;AAAA,IACzB;AAEA,SAAK,gBAAgB,KAAK,eAAe,MAAM,QAAQ,cAAc,KAAK;AAC1E,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,MAAc,eACZ,MACA,QACA,cACA,OAC2C;AAC3C,SAAK,SAAS;AAEd,QAAI,CAAC,SAAS,cAAc;AAC1B,YAAM,kBAAkB,MAAM,KAAK,KAAK,cAAc,OAAO,CAAC,EAAE;AAAA,QAC9D,CAAC,MACC,IAAI,QAAc,CAAC,YAAY;AAC7B,gBAAM,cAAc,EAAE;AACtB,gBAAM,aAAa,EAAE;AACrB,YAAE,UAAU,CAAC,MAAe;AAC1B,wBAAY,CAAC;AACb,oBAAQ;AAAA,UACV;AACA,YAAE,SAAS,CAAC,MAAe;AACzB,uBAAW,CAAC;AACZ,oBAAQ;AAAA,UACV;AAAA,QACF,CAAC;AAAA,MACL;AACA,UAAI,gBAAgB,SAAS,GAAG;AAC9B,cAAM,QAAQ,WAAW,eAAe;AAAA,MAC1C;AAAA,IACF;AAEA,WAAO,IAAI,QAA0C,CAAC,YAAY;AAChE,UAAI,CAAC,KAAK,OAAO,KAAK,IAAI,eAAe,UAAU,QAAQ;AACzD,aAAK,SAAS;AACd,aAAK,SAAS;AACd,cAAM,SAAS,EAAE,MAAM,OAAO;AAC9B,aAAK,KAAK,SAAS,MAAM;AACzB,gBAAQ,MAAM;AACd;AAAA,MACF;AAEA,YAAM,UAAU,CAAC,UAAsB;AACrC,aAAK,KAAK,oBAAoB,SAAS,OAAO;AAC9C,aAAK,SAAS;AACd,aAAK,SAAS;AACd,cAAM,SAAS,EAAE,MAAM,MAAM,MAAM,QAAQ,MAAM,OAAO;AACxD,aAAK,KAAK,SAAS,MAAM;AACzB,gBAAQ,MAAM;AAAA,MAChB;AAEA,WAAK,IAAI,iBAAiB,SAAS,OAAO;AAE1C,UAAI,OAAO;AAET,aAAK,IAAI,MAAM;AAAA,MACjB,OAAO;AAEL,cAAM,YACJ,QAAQ,OAAQ,QAAQ,QAAQ,CAAC,CAAC,MAAM,MAAM,IAAI,EAAE,SAAS,IAAI;AACnE,aAAK,IAAI,MAAM,YAAY,OAAO,KAAM,MAAM;AAAA,MAChD;AAAA,IACF,CAAC;AAAA,EACH;AAAA;AAAA,EAsCA,UAAU,MAAmB;AAC3B,QAAI,KAAK,WAAW,KAAK,OAAO,KAAK,CAAC,MAAM,YAAY;AACtD,WAAK,mBAAmB,KAAK,CAAC;AAAA,IAChC,WACE,KAAK,WAAW,KAChB,OAAO,KAAK,CAAC,MAAM,YACnB,OAAO,KAAK,CAAC,MAAM,YACnB;AACA,WAAK,UAAU,IAAI,KAAK,CAAC,GAAG,KAAK,CAAC,CAAgB;AAAA,IACpD,WACE,KAAK,WAAW,KAChB,OAAO,KAAK,CAAC,MAAM,YACnB,OAAO,KAAK,CAAC,MAAM,YACnB,OAAO,KAAK,CAAC,MAAM,YACnB;AACA,WAAK,UAAU,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC,CAAgB;AAAA,IACpE,OAAO;AACL,YAAM,IAAI;AAAA,QACR;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAIA,cAAc,iBAA0B,QAAuB;AAC7D,QAAI,mBAAmB,QAAQ;AAC7B,WAAK,UAAU,OAAO,GAAG,eAAe,IAAI,MAAM,EAAE;AAAA,IACtD,WAAW,iBAAiB;AAC1B,WAAK,UAAU,OAAO,eAAe;AAAA,IACvC,OAAO;AACL,WAAK,mBAAmB;AAAA,IAC1B;AAAA,EACF;AAAA,EAEA,oBAA0B;AACxB,SAAK,UAAU,MAAM;AACrB,SAAK,mBAAmB;AAAA,EAC1B;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,IAAI,YAAyD;AAC3D,SAAK,YAAY,IAAI,UAAU;AAAA,EACjC;AAAA,EA6BA,MAAM,QAAQ,MAAmC;AAC/C,QAAI;AACJ,QAAI;AACJ,QAAI;AAEJ,QACE,KAAK,UAAU,KACf,OAAO,KAAK,CAAC,MAAM,YACnB,OAAO,KAAK,CAAC,MAAM,UACnB;AAEA,eAAS,KAAK,CAAC;AACf,eAAS,KAAK,CAAC,KAAK,CAAC;AACrB,gBAAW,KAAK,CAAC,KAAqB,CAAC;AAAA,IACzC,OAAO;AAEL,eAAS,KAAK,CAAC;AACf,eAAS,KAAK,CAAC,KAAK,CAAC;AACrB,gBAAW,KAAK,CAAC,KAAqB,CAAC;AAAA,IACzC;AAEA,QAAI,KAAK,WAAW,MAAM;AACxB,YAAM,IAAI,MAAM,mCAAmC,KAAK,MAAM,EAAE;AAAA,IAClE;AAEA,WAAO,KAAK,WAAW,KAAK,MAAM,KAAK,UAAU,QAAQ,QAAQ,OAAO,CAAC;AAAA,EAC3E;AAAA,EAEA,MAAc,UACZ,QACA,QACA,SACkB;AAClB,UAAM,QAAQ,KAAK,mBAAmB;AACtC,UAAM,YAAY,QAAQ,aAAa,KAAK,SAAS;AAErD,UAAM,MAAyB;AAAA,MAC7B,MAAM;AAAA,MACN,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAEA,QAAI;AAEJ,UAAM,KAAK,YAAY,QAAQ,KAAK,OAAO,MAAM;AAC/C,YAAM,UAAU;AAKhB,YAAM,UAAoB;AAAA,QACxB,YAAY;AAAA,QACZ;AAAA,QACA,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AACA,YAAM,aAAa,KAAK,UAAU,OAAO;AAEzC,mBAAa,MAAM,IAAI,QAAiB,CAAC,SAAS,WAAW;AAC3D,cAAM,gBAAgB,WAAW,MAAM;AACrC,eAAK,cAAc,OAAO,KAAK;AAC/B,eAAK,QAAQ,OAAO,kBAAkB;AAAA,YACpC,WAAW;AAAA,YACX,QAAQ,QAAQ;AAAA,YAChB;AAAA,UACF,CAAC;AACD;AAAA,YACE,IAAI;AAAA,cACF,YAAY,QAAQ,MAAM,qBAAqB,SAAS;AAAA,YAC1D;AAAA,UACF;AAAA,QACF,GAAG,SAAS;AAEZ,cAAM,UAAuB;AAAA,UAC3B;AAAA,UACA;AAAA,UACA;AAAA,UACA,QAAQ,QAAQ;AAAA,UAChB,QAAQ,KAAK,IAAI;AAAA,QACnB;AAGA,YAAI,QAAQ,QAAQ;AAClB,cAAI,QAAQ,OAAO,SAAS;AAC1B,yBAAa,aAAa;AAC1B,mBAAO,QAAQ,OAAO,UAAU,IAAI,MAAM,SAAS,CAAC;AACpD;AAAA,UACF;AACA,gBAAM,eAAe,MAAM;AACzB,yBAAa,aAAa;AAC1B,iBAAK,cAAc,OAAO,KAAK;AAC/B,mBAAO,QAAQ,QAAQ,UAAU,IAAI,MAAM,SAAS,CAAC;AAAA,UACvD;AACA,kBAAQ,OAAO,iBAAiB,SAAS,cAAc;AAAA,YACrD,MAAM;AAAA,UACR,CAAC;AACD,kBAAQ,eAAe;AAAA,QACzB;AAEA,aAAK,cAAc,IAAI,OAAO,OAAO;AACrC,aAAK,KAAK,KAAK,UAAU;AACzB,aAAK,KAAK,WAAW,OAAO;AAC5B,aAAK,KAAK,QAAQ,OAAO;AAAA,MAC3B,CAAC;AAAA,IACH,CAAC;AAED,WAAO;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,QAAQ,SAAuB;AAC7B,QAAI,KAAK,WAAW,QAAQ,KAAK,KAAK;AACpC,WAAK,IAAI,KAAK,OAAO;AAAA,IACvB,WAAW,KAAK,WAAW,YAAY;AACrC,WAAK,gBAAgB,KAAK,OAAO;AAAA,IACnC,OAAO;AACL,YAAM,IAAI,MAAM,sCAAsC;AAAA,IACxD;AAAA,EACF;AAAA;AAAA,EAIA,YAAY,SAA8C;AACxD,WAAO,OAAO,KAAK,UAAU,OAAO;AAEpC,QAAI,QAAQ,oBAAoB,QAAW;AACzC,WAAK,WAAW,eAAe,QAAQ,eAAe;AAAA,IACxD;AAAA,EACF;AAAA;AAAA,EAIQ,iBAAiB,IAAqB;AAC5C,OAAG;AAAA,MAAiB;AAAA,MAAW,CAAC,UAC9B,KAAK,WAAW,MAAM,IAAI;AAAA,IAC5B;AACA,OAAG;AAAA,MAAiB;AAAA,MAAS,CAAC,UAC5B,KAAK,SAAS,MAAM,MAAM,MAAM,MAAM;AAAA,IACxC;AACA,OAAG,iBAAiB,SAAS,CAAC,UAAiB,KAAK,KAAK,SAAS,KAAK,CAAC;AAAA,EAC1E;AAAA;AAAA,EAIQ,WAAW,MAAqB;AACtC,UAAM,MAAM,OAAO,SAAS,WAAW,OAAO,OAAO,IAAI;AAEzD,QAAI;AACJ,QAAI;AACF,gBAAU,KAAK,MAAM,GAAG;AACxB,UAAI,CAAC,MAAM,QAAQ,OAAO,EAAG,OAAM,IAAI,MAAM,yBAAyB;AAAA,IACxE,SAAS,KAAK;AACZ,WAAK,cAAc,KAAK,GAAY;AACpC;AAAA,IACF;AAEA,UAAM,cAAc,QAAQ,CAAC;AAE7B,YAAQ,aAAa;AAAA,MACnB,KAAK,YAAY;AACf,aAAK,oBAAoB,OAAmB;AAC5C;AAAA,MACF,KAAK,YAAY;AACf,aAAK,kBAAkB,OAAyB;AAChD;AAAA,MACF,KAAK,YAAY;AACf,aAAK,iBAAiB,OAAwB;AAC9C;AAAA,MACF;AACE,aAAK;AAAA,UACH,KAAK,UAAU,OAAO;AAAA,UACtB,IAAI;AAAA,YACF,yBAAyB,WAAW;AAAA,UACtC;AAAA,QACF;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,MAAc,oBAAoB,SAAkC;AAClE,UAAM,CAAC,EAAE,OAAO,QAAQ,MAAM,IAAI;AAElC,UAAM,MAAyB;AAAA,MAC7B,MAAM;AAAA,MACN,WAAW;AAAA,MACX;AAAA,MACA;AAAA,MACA,UAAU,KAAK;AAAA,IACjB;AAEA,UAAM,KAAK,YAAY,QAAQ,KAAK,OAAO,MAAM;AAC/C,YAAM,UAAU;AAKhB,YAAM,kBAA4B;AAAA,QAChC,YAAY;AAAA,QACZ,QAAQ;AAAA,QACR,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AACA,WAAK,KAAK,QAAQ,eAAe;AAEjC,UAAI,KAAK,WAAW,MAAM;AACxB;AAAA,MACF;AAEA,UAAI;AACF,YAAI,KAAK,kBAAkB,IAAI,QAAQ,SAAS,GAAG;AACjD,gBAAM;AAAA,YACJ;AAAA,YACA,oCAAoC,QAAQ,SAAS;AAAA,UACvD;AAAA,QACF;AAEA,cAAM,mBACH,KAAK,YACF,KAAK,UAAU,IAAI,GAAG,KAAK,SAAS,IAAI,QAAQ,MAAM,EAAE,IACxD,WAAc,KAAK,UAAU,IAAI,QAAQ,MAAM;AAErD,YAAI,CAAC,mBAAmB,CAAC,KAAK,kBAAkB;AAC9C,gBAAM;AAAA,YACJ;AAAA,YACA,0BAA0B,QAAQ,MAAM;AAAA,UAC1C;AAAA,QACF;AAEA,aAAK,kBAAkB,IAAI,QAAQ,SAAS;AAE5C,cAAM,KAAK,IAAI,gBAAgB;AAC/B,cAAM,UAA0B;AAAA,UAC9B,WAAW,QAAQ;AAAA,UACnB,QAAQ,QAAQ;AAAA,UAChB,UAAU,KAAK;AAAA,UACf,QAAQ,QAAQ;AAAA,UAChB,QAAQ,GAAG;AAAA,QACb;AAEA,YAAI;AACJ,YAAI,iBAAiB;AACnB,mBAAS,MAAM,gBAAgB,OAAO;AAAA,QACxC,WAAW,KAAK,kBAAkB;AAChC,mBAAS,MAAM,KAAK,iBAAiB,QAAQ,QAAQ,OAAO;AAAA,QAC9D;AAEA,aAAK,kBAAkB,OAAO,QAAQ,SAAS;AAE/C,YAAI,WAAW,QAAS;AAExB,cAAM,WAA2B;AAAA,UAC/B,YAAY;AAAA,UACZ,QAAQ;AAAA,UACR;AAAA,QACF;AACA,aAAK,KAAK,KAAK,KAAK,UAAU,QAAQ,CAAC;AACvC,aAAK,KAAK,cAAc,QAAQ;AAAA,MAClC,SAAS,KAAK;AACZ,aAAK,kBAAkB,OAAO,QAAQ,SAAS;AAC/C,aAAK,QAAQ,QAAQ,iBAAiB;AAAA,UACpC,WAAW,QAAQ;AAAA,UACnB,QAAQ,QAAQ;AAAA,UAChB,OAAQ,IAAc;AAAA,QACxB,CAAC;AAED,cAAM,SACJ,eAAe,mBAAoB,IAAiB,eAC/C,MACD,eAAe,iBAAkB,IAAc,OAAO;AAE5D,cAAM,UAAU,KAAK,SAAS,4BAC1B,oBAAoB,GAAY,IAChC,CAAC;AAEL,cAAM,gBAA+B;AAAA,UACnC,YAAY;AAAA,UACZ,QAAQ;AAAA,UACR,OAAO;AAAA,UACP,OAAO,mBAAoB,IAAc,WAAW;AAAA,UACpD;AAAA,QACF;AACA,aAAK,KAAK,KAAK,KAAK,UAAU,aAAa,CAAC;AAC5C,aAAK,KAAK,aAAa,aAAa;AAAA,MACtC;AAAA,IACF,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,kBAAkB,SAAwC;AACtE,UAAM,CAAC,EAAE,OAAO,MAAM,IAAI;AAE1B,QAAI,CAAC,KAAK,cAAc,IAAI,KAAK,GAAG;AAClC,WAAK,QAAQ,OAAO,6CAA6C;AAAA,QAC/D,WAAW;AAAA,MACb,CAAC;AACD;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,cAAc,IAAI,KAAK;AAE5C,UAAM,MAAyB;AAAA,MAC7B,MAAM;AAAA,MACN,WAAW;AAAA,MACX,QAAQ,QAAQ;AAAA,MAChB,SAAS;AAAA,IACX;AAEA,UAAM,KAAK,YAAY,QAAQ,KAAK,OAAO,MAAM;AAC/C,YAAM,UAAU;AAKhB,YAAM,kBAAkC;AAAA,QACtC,YAAY;AAAA,QACZ;AAAA,QACA,QAAQ;AAAA,MACV;AACA,WAAK,KAAK,cAAc,eAAe;AAEvC,mBAAa,QAAQ,aAAa;AAClC,WAAK,cAAc,OAAO,KAAK;AAC/B,cAAQ,QAAQ,QAAQ,OAAO;AAAA,IACjC,CAAC;AAAA,EACH;AAAA,EAEA,MAAc,iBAAiB,SAAuC;AACpE,UAAM,CAAC,EAAE,OAAO,WAAW,cAAc,YAAY,IAAI;AAEzD,QAAI,CAAC,KAAK,cAAc,IAAI,KAAK,GAAG;AAClC,WAAK,QAAQ,OAAO,4CAA4C;AAAA,QAC9D,WAAW;AAAA,MACb,CAAC;AACD;AAAA,IACF;AAEA,UAAM,UAAU,KAAK,cAAc,IAAI,KAAK;AAE5C,UAAM,QAAQ,eAAe,WAAW,cAAc,YAAY;AAElE,UAAM,MAAyB;AAAA,MAC7B,MAAM;AAAA,MACN,WAAW;AAAA,MACX,QAAQ,QAAQ;AAAA,MAChB;AAAA;AAAA,IACF;AAEA,UAAM,KAAK,YAAY,QAAQ,KAAK,OAAO,MAAM;AAC/C,YAAM,UAAU;AAMhB,YAAM,iBAAiB,QAAQ;AAE/B,YAAM,kBAAiC;AAAA,QACrC,YAAY;AAAA,QACZ;AAAA,QACA,eAAe;AAAA,QACf,eAAe;AAAA,QACf,eAAe,mBAAmB,CAAC;AAAA,MACrC;AACA,WAAK,KAAK,aAAa,eAAe;AAEtC,mBAAa,QAAQ,aAAa;AAClC,WAAK,cAAc,OAAO,KAAK;AAC/B,cAAQ,OAAO,cAAc;AAAA,IAC/B,CAAC;AAAA,EACH;AAAA;AAAA,EAIQ,cAAc,YAAoB,OAAoB;AAC5D,SAAK;AACL,SAAK,SAAS,OAAO,eAAe;AAAA,MAClC,OAAO,MAAM;AAAA,MACb,OAAO,KAAK;AAAA,IACd,CAAC;AACD,SAAK,KAAK,cAAc,EAAE,SAAS,YAAY,MAAM,CAAC;AAGtD,UAAM,QAAQ,WAAW,MAAM,4BAA4B;AAC3D,QAAI,QAAQ,CAAC,KAAK,KAAK,KAAK;AAC1B,YAAM,gBAA+B;AAAA,QACnC,YAAY;AAAA,QACZ,MAAM,CAAC;AAAA,QACP;AAAA,QACA,MAAM,WAAW;AAAA,QACjB,CAAC;AAAA,MACH;AACA,WAAK,IAAI,KAAK,KAAK,UAAU,aAAa,CAAC;AAC3C,WAAK,KAAK,aAAa,aAAa;AAAA,IACtC;AAEA,QAAI,KAAK,oBAAoB,KAAK,SAAS,gBAAgB;AACzD,WAAK,MAAM,EAAE,MAAM,MAAM,QAAQ,wBAAwB,CAAC,EAAE;AAAA,QAC1D,MAAM;AAAA,QAAC;AAAA,MACT;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,oBAAoB,QAAsB;AAChD,eAAW,CAAC,EAAE,OAAO,KAAK,KAAK,eAAe;AAC5C,mBAAa,QAAQ,aAAa;AAClC,cAAQ,OAAO,IAAI,MAAM,MAAM,CAAC;AAAA,IAClC;AACA,SAAK,cAAc,MAAM;AACzB,SAAK,kBAAkB,MAAM;AAAA,EAC/B;AAAA,EAEQ,SAAS,MAAc,QAAsB;AACnD,SAAK,oBAAoB,sBAAsB,IAAI,KAAK,MAAM,GAAG;AAEjE,QAAI,KAAK,WAAW,SAAS;AAE3B,WAAK,SAAS,OAAO,gBAAgB,EAAE,MAAM,OAAO,CAAC;AACrD,WAAK,KAAK,cAAc,EAAE,MAAM,OAAO,CAAC;AAExC,UACE,KAAK,SAAS,aACd,KAAK,oBAAoB,KAAK,SAAS,eACvC;AACA,aAAK,mBAAmB;AAAA,MAC1B,OAAO;AAEL,aAAK,SAAS;AACd,aAAK,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAAA,MACrC;AAAA,IACF,OAAO;AACL,WAAK,SAAS;AAAA,IAEhB;AAAA,EACF;AAAA;AAAA;AAAA,EAKA,OAAwB,sBAAsB,oBAAI,IAAI;AAAA,IACpD;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EACF,CAAC;AAAA,EAEO,qBAA2B;AACjC,SAAK;AACL,SAAK,SAAS;AAGd,UAAM,OAAO,KAAK,SAAS;AAC3B,UAAM,MAAM,KAAK,SAAS;AAC1B,UAAM,UAAU,KAAK;AAAA,MACnB;AAAA,MACA,OAAO,MAAM,KAAK,oBAAoB,MAAM,MAAM,KAAK,OAAO,IAAI;AAAA,IACpE;AAEA,SAAK,SAAS,OAAO,gBAAgB;AAAA,MACnC,SAAS,KAAK;AAAA,MACd,SAAS,KAAK,MAAM,OAAO;AAAA,IAC7B,CAAC;AACD,SAAK,KAAK,aAAa,EAAE,SAAS,KAAK,mBAAmB,OAAO,QAAQ,CAAC;AAE1E,SAAK,kBAAkB,WAAW,YAAY;AAC5C,WAAK,kBAAkB;AACvB,UAAI;AACF,cAAM,KAAK,iBAAiB;AAAA,MAC9B,SAAS,KAAK;AAEZ,cAAM,MAAM,eAAe,QAAQ,IAAI,UAAU;AACjD,YAAI,mBAAkB,oBAAoB,IAAI,GAAG,GAAG;AAClD,eAAK,SAAS,QAAQ,kDAA6C;AAAA,YACjE,OAAO;AAAA,UACT,CAAC;AACD,eAAK,SAAS;AACd,eAAK,KAAK,SAAS,EAAE,MAAM,MAAM,QAAQ,IAAI,CAAC;AAC9C;AAAA,QACF;AAEA,YACE,KAAK,oBAAoB,KAAK,SAAS,iBACvC,KAAK,SAAS,WACd;AACA,eAAK,mBAAmB;AAAA,QAC1B,OAAO;AAEL,eAAK,SAAS;AACd,eAAK,KAAK,SAAS;AAAA,YACjB,MAAM;AAAA,YACN,QAAQ;AAAA,UACV,CAAC;AAAA,QACH;AAAA,MACF;AAAA,IACF,GAAG,OAAO;AAAA,EACZ;AAAA;AAAA,EAIQ,iBAAyB;AAC/B,QAAI,MAAM,KAAK,SAAS;AAExB,QAAI,CAAC,IAAI,SAAS,GAAG,EAAG,QAAO;AAC/B,WAAO,mBAAmB,KAAK,SAAS;AAExC,QAAI,KAAK,SAAS,OAAO;AACvB,YAAM,SAAS,IAAI,gBAAgB,KAAK,SAAS,KAAK;AACtD,cAAQ,IAAI,SAAS,GAAG,IAAI,MAAM,OAAO,OAAO,SAAS;AAAA,IAC3D;AAEA,WAAO;AAAA,EACT;AAAA;AAAA,EAIQ,WAAiB;AACvB,SAAK,gBAAgB;AACrB,SAAK,MAAM;AAAA,EACb;AAAA;AAAA,EAIQ,qBAA6B;AAEnC,QACE,OAAO,WAAW,eAClB,OAAO,OAAO,eAAe,YAC7B;AACA,aAAO,OAAO,WAAW;AAAA,IAC3B;AAGA,WAAO,uCAAuC,QAAQ,SAAS,CAAC,MAAM;AACpE,YAAM,IAAK,KAAK,OAAO,IAAI,KAAM;AACjC,YAAM,IAAI,MAAM,MAAM,IAAK,IAAI,IAAO;AACtC,aAAO,EAAE,SAAS,EAAE;AAAA,IACtB,CAAC;AAAA,EACH;AACF;","names":[]}
|