@adofai-ipc/client 0.2.0 → 0.4.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 KGH1113
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -40,6 +40,24 @@ await tufhelper.call("level.open-from-id", {
40
40
 
41
41
  Finds a running AdofaiIpc server by probing `/ipc/health`.
42
42
 
43
+ The client and server product versions must match exactly. A mismatch throws
44
+ `IpcVersionMismatchError` and stops port probing. Use `onVersionMismatch` to display application UI;
45
+ the callback runs at most once per `tryConnect` call and does not suppress the typed error.
46
+
47
+ ```ts
48
+ await tryConnect({
49
+ onVersionMismatch(error) {
50
+ if (error.direction === "client_outdated") location.reload();
51
+ else openAdofaiIpcDownloadNotice(error);
52
+ }
53
+ });
54
+ ```
55
+
56
+ `server_outdated` means the mod must be updated, `client_outdated` means the web bundle must be
57
+ updated, and `legacy_server` means the server did not provide a valid product version. React
58
+ StrictMode and consumer retry loops can call `tryConnect` more than once, so applications should
59
+ store mismatch as a terminal connection state and deduplicate their own modal or banner.
60
+
43
61
  Defaults:
44
62
 
45
63
  - host: `127.0.0.1`
package/dist/index.cjs CHANGED
@@ -23,10 +23,12 @@ __export(index_exports, {
23
23
  AdofaiIpcClient: () => AdofaiIpcClient,
24
24
  AdofaiIpcError: () => AdofaiIpcError,
25
25
  AdofaiIpcNamespaceClient: () => AdofaiIpcNamespaceClient,
26
+ CLIENT_VERSION: () => CLIENT_VERSION,
26
27
  IpcConnectionError: () => IpcConnectionError,
27
28
  IpcHttpError: () => IpcHttpError,
28
29
  IpcResponseError: () => IpcResponseError,
29
30
  IpcTimeoutError: () => IpcTimeoutError,
31
+ IpcVersionMismatchError: () => IpcVersionMismatchError,
30
32
  isIpcUnavailable: () => isIpcUnavailable,
31
33
  tryConnect: () => tryConnect
32
34
  });
@@ -57,6 +59,18 @@ var IpcTimeoutError = class extends IpcConnectionError {
57
59
  this.timeoutMs = timeoutMs;
58
60
  }
59
61
  };
62
+ var IpcVersionMismatchError = class extends AdofaiIpcError {
63
+ constructor(options) {
64
+ const server = options.serverVersion ?? "legacy/unknown";
65
+ super(`AdofaiIpc version mismatch: client ${options.clientVersion}, server ${server}.`);
66
+ this.code = "VERSION_MISMATCH";
67
+ this.name = "IpcVersionMismatchError";
68
+ this.clientVersion = options.clientVersion;
69
+ this.serverVersion = options.serverVersion;
70
+ this.direction = options.direction;
71
+ this.protocolVersion = options.protocolVersion;
72
+ }
73
+ };
60
74
  function isIpcUnavailable(error) {
61
75
  return error instanceof IpcConnectionError && error.code === "UNAVAILABLE";
62
76
  }
@@ -76,6 +90,43 @@ var IpcResponseError = class extends AdofaiIpcError {
76
90
  }
77
91
  };
78
92
 
93
+ // src/version.ts
94
+ var CLIENT_VERSION = "0.4.0";
95
+ var CANONICAL_SEMVER = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?$/;
96
+ function compareProductVersions(left, right) {
97
+ const leftVersion = parseProductVersion(left);
98
+ const rightVersion = parseProductVersion(right);
99
+ if (!leftVersion || !rightVersion) return null;
100
+ for (let index = 0; index < leftVersion.core.length; index++) {
101
+ const difference = leftVersion.core[index] - rightVersion.core[index];
102
+ if (difference !== 0) return difference < 0 ? -1 : 1;
103
+ }
104
+ if (leftVersion.prerelease === null) return rightVersion.prerelease === null ? 0 : 1;
105
+ if (rightVersion.prerelease === null) return -1;
106
+ const length = Math.max(leftVersion.prerelease.length, rightVersion.prerelease.length);
107
+ for (let index = 0; index < length; index++) {
108
+ const leftPart = leftVersion.prerelease[index];
109
+ const rightPart = rightVersion.prerelease[index];
110
+ if (leftPart === void 0) return -1;
111
+ if (rightPart === void 0) return 1;
112
+ if (leftPart === rightPart) continue;
113
+ const leftNumeric = /^\d+$/.test(leftPart);
114
+ const rightNumeric = /^\d+$/.test(rightPart);
115
+ if (leftNumeric && rightNumeric) return Number(leftPart) < Number(rightPart) ? -1 : 1;
116
+ if (leftNumeric !== rightNumeric) return leftNumeric ? -1 : 1;
117
+ return leftPart < rightPart ? -1 : 1;
118
+ }
119
+ return 0;
120
+ }
121
+ function parseProductVersion(value) {
122
+ const match = CANONICAL_SEMVER.exec(value);
123
+ if (!match) return null;
124
+ return {
125
+ core: [Number(match[1]), Number(match[2]), Number(match[3])],
126
+ prerelease: match[4] ? match[4].split(".") : null
127
+ };
128
+ }
129
+
79
130
  // src/client.ts
80
131
  var DEFAULT_HOST = "127.0.0.1";
81
132
  var DEFAULT_START_PORT = 32145;
@@ -239,6 +290,7 @@ async function tryConnect(options = {}) {
239
290
  const endPort = options.endPort ?? DEFAULT_END_PORT;
240
291
  const probeTimeoutMs = options.probeTimeoutMs ?? options.timeoutMs ?? DEFAULT_PROBE_TIMEOUT_MS;
241
292
  const requestTimeoutMs = options.requestTimeoutMs ?? options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
293
+ let lastProbeError;
242
294
  for (let port = startPort; port <= endPort; port++) {
243
295
  const client = new AdofaiIpcClient({
244
296
  baseUrl: `http://${host}:${port}`,
@@ -248,19 +300,42 @@ async function tryConnect(options = {}) {
248
300
  try {
249
301
  const health = await client.health();
250
302
  if (health.ok && health.server === "AdofaiIpc") {
303
+ const mismatch = getVersionMismatch(health);
304
+ if (mismatch) {
305
+ try {
306
+ options.onVersionMismatch?.(mismatch);
307
+ } catch {
308
+ }
309
+ throw mismatch;
310
+ }
251
311
  return new AdofaiIpcClient({
252
312
  baseUrl: client.baseUrl,
253
313
  fetch: options.fetch,
254
314
  requestTimeoutMs
255
315
  });
256
316
  }
257
- } catch {
317
+ } catch (error) {
318
+ if (error instanceof IpcVersionMismatchError) throw error;
319
+ lastProbeError = error;
258
320
  }
259
321
  }
322
+ if (lastProbeError instanceof IpcTimeoutError) throw lastProbeError;
260
323
  throw new IpcConnectionError(
261
324
  `Could not connect to AdofaiIpc on ${host}:${startPort}-${endPort}.`
262
325
  );
263
326
  }
327
+ function getVersionMismatch(health) {
328
+ const protocolVersion = Number.isInteger(health.protocolVersion) ? health.protocolVersion : null;
329
+ const serverVersion = typeof health.serverVersion === "string" ? health.serverVersion : null;
330
+ const comparison = serverVersion === null ? null : compareProductVersions(serverVersion, CLIENT_VERSION);
331
+ if (comparison === 0 && serverVersion === CLIENT_VERSION) return null;
332
+ return new IpcVersionMismatchError({
333
+ clientVersion: CLIENT_VERSION,
334
+ serverVersion,
335
+ direction: comparison === null ? "legacy_server" : comparison < 0 ? "server_outdated" : "client_outdated",
336
+ protocolVersion
337
+ });
338
+ }
264
339
  function normalizeBaseUrl(value) {
265
340
  return value.replace(/\/+$/, "");
266
341
  }
@@ -295,10 +370,12 @@ function createRequestId() {
295
370
  AdofaiIpcClient,
296
371
  AdofaiIpcError,
297
372
  AdofaiIpcNamespaceClient,
373
+ CLIENT_VERSION,
298
374
  IpcConnectionError,
299
375
  IpcHttpError,
300
376
  IpcResponseError,
301
377
  IpcTimeoutError,
378
+ IpcVersionMismatchError,
302
379
  isIpcUnavailable,
303
380
  tryConnect
304
381
  });
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/client.ts"],"sourcesContent":["export {\n AdofaiIpcClient,\n AdofaiIpcNamespaceClient,\n tryConnect\n} from \"./client\";\n\nexport {\n AdofaiIpcError,\n IpcConnectionError,\n IpcHttpError,\n IpcResponseError,\n IpcTimeoutError,\n isIpcUnavailable\n} from \"./errors\";\n\nexport type {\n IpcConnectionErrorCode,\n IpcConnectionErrorOptions\n} from \"./errors\";\n\nexport type {\n AdofaiIpcClientOptions,\n IpcCallOptions,\n IpcErrorInfo,\n IpcErrorResponse,\n IpcHealthResponse,\n IpcNamespaceDetail,\n IpcNamespaceErrorInfo,\n IpcNamespaceStatus,\n IpcNamespacesResponse,\n IpcNamespaceSummary,\n IpcRequestId,\n IpcRequestOptions,\n IpcResponse,\n IpcSuccessResponse,\n TryConnectOptions,\n WaitForNamespaceOptions\n} from \"./types\";\n","import type { IpcErrorInfo } from \"./types\";\n\nexport type IpcConnectionErrorCode = \"UNAVAILABLE\" | \"TIMEOUT\";\n\nexport interface IpcConnectionErrorOptions {\n code?: IpcConnectionErrorCode;\n cause?: unknown;\n}\n\nexport class AdofaiIpcError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"AdofaiIpcError\";\n }\n}\n\nexport class IpcConnectionError extends AdofaiIpcError {\n readonly code: IpcConnectionErrorCode;\n readonly cause?: unknown;\n\n constructor(\n message = \"Could not connect to AdofaiIpc.\",\n options: IpcConnectionErrorOptions = {}\n ) {\n super(message);\n this.name = \"IpcConnectionError\";\n this.code = options.code ?? \"UNAVAILABLE\";\n this.cause = options.cause;\n }\n}\n\nexport class IpcTimeoutError extends IpcConnectionError {\n readonly timeoutMs: number;\n\n constructor(timeoutMs: number, options: Pick<IpcConnectionErrorOptions, \"cause\"> = {}) {\n super(`AdofaiIpc request timed out after ${timeoutMs} ms.`, {\n code: \"TIMEOUT\",\n cause: options.cause\n });\n this.name = \"IpcTimeoutError\";\n this.timeoutMs = timeoutMs;\n }\n}\n\nexport function isIpcUnavailable(error: unknown): error is IpcConnectionError {\n return error instanceof IpcConnectionError && error.code === \"UNAVAILABLE\";\n}\n\nexport class IpcHttpError extends AdofaiIpcError {\n readonly status: number;\n\n constructor(status: number, message: string) {\n super(message);\n this.name = \"IpcHttpError\";\n this.status = status;\n }\n}\n\nexport class IpcResponseError extends AdofaiIpcError {\n readonly code: string;\n readonly error: IpcErrorInfo;\n\n constructor(error: IpcErrorInfo) {\n super(error.message);\n this.name = \"IpcResponseError\";\n this.code = error.code;\n this.error = error;\n }\n}\n","import {\n IpcConnectionError,\n IpcHttpError,\n IpcResponseError,\n IpcTimeoutError\n} from \"./errors\";\nimport type {\n AdofaiIpcClientOptions,\n IpcCallOptions,\n IpcErrorInfo,\n IpcHealthResponse,\n IpcNamespaceDetail,\n IpcNamespacesResponse,\n IpcRequestId,\n IpcRequestOptions,\n IpcResponse,\n TryConnectOptions,\n WaitForNamespaceOptions\n} from \"./types\";\n\nconst DEFAULT_HOST = \"127.0.0.1\";\nconst DEFAULT_START_PORT = 32145;\nconst DEFAULT_END_PORT = 32155;\nconst DEFAULT_PROBE_TIMEOUT_MS = 500;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 10_000;\nconst DEFAULT_NAMESPACE_WAIT_TIMEOUT_MS = 10_000;\nconst DEFAULT_NAMESPACE_POLL_INTERVAL_MS = 100;\n\nexport class AdofaiIpcClient {\n readonly baseUrl: string;\n\n private readonly fetchImpl: typeof fetch;\n private readonly requestTimeoutMs: number;\n\n constructor(options: AdofaiIpcClientOptions = {}) {\n this.baseUrl = normalizeBaseUrl(options.baseUrl ?? `http://${DEFAULT_HOST}:${DEFAULT_START_PORT}`);\n this.fetchImpl = options.fetch ?? globalThis.fetch;\n this.requestTimeoutMs =\n options.requestTimeoutMs ?? options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n\n if (!this.fetchImpl) {\n throw new IpcConnectionError(\"A fetch implementation is required.\");\n }\n }\n\n static async connect(options: TryConnectOptions = {}): Promise<AdofaiIpcClient> {\n return tryConnect(options);\n }\n\n async health(options: IpcRequestOptions = {}): Promise<IpcHealthResponse> {\n return this.get<IpcHealthResponse>(\"/ipc/health\", options);\n }\n\n async listNamespaces(options: IpcRequestOptions = {}): Promise<IpcNamespacesResponse> {\n return this.get<IpcNamespacesResponse>(\"/ipc/namespaces\", options);\n }\n\n async getNamespace(\n namespace: string,\n options: IpcRequestOptions = {}\n ): Promise<IpcNamespaceDetail> {\n return this.get<IpcNamespaceDetail>(\n `/ipc/namespaces/${encodeURIComponent(namespace)}`,\n options\n );\n }\n\n async waitForNamespace(\n namespace: string,\n options: WaitForNamespaceOptions = {}\n ): Promise<IpcNamespaceDetail> {\n const timeoutMs = options.timeoutMs ?? DEFAULT_NAMESPACE_WAIT_TIMEOUT_MS;\n const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_NAMESPACE_POLL_INTERVAL_MS;\n const requiredStatus = options.status ?? \"registered\";\n const deadline = Date.now() + timeoutMs;\n let stateError: IpcResponseError | undefined;\n\n while (true) {\n try {\n const detail = await this.getNamespace(namespace, {\n timeoutMs: options.requestTimeoutMs\n });\n\n if (requiredStatus === \"registered\" || detail.status === \"ready\") {\n return detail;\n }\n\n if (detail.status === \"error\") {\n throw new IpcResponseError({\n code: \"namespace_error\",\n message: detail.error?.message ?? `Namespace initialization failed: ${namespace}`\n });\n }\n\n if (detail.status !== \"initializing\") {\n throw new IpcResponseError({\n code: \"namespace_status_unavailable\",\n message: `Namespace status is unavailable: ${namespace}`\n });\n }\n\n stateError = new IpcResponseError({\n code: \"namespace_initializing\",\n message: `Namespace is initializing: ${namespace}`\n });\n } catch (error) {\n if (\n !(error instanceof IpcResponseError) ||\n (error.code !== \"namespace_not_found\" && error.code !== \"namespace_initializing\")\n ) {\n throw error;\n }\n\n stateError = error;\n }\n\n const remainingMs = deadline - Date.now();\n if (remainingMs <= 0) {\n throw stateError ?? new IpcResponseError({\n code: \"namespace_initializing\",\n message: `Namespace is initializing: ${namespace}`\n });\n }\n\n await delay(Math.min(pollIntervalMs, remainingMs));\n }\n }\n\n namespace(namespace: string): AdofaiIpcNamespaceClient {\n return new AdofaiIpcNamespaceClient(this, namespace);\n }\n\n async call<TResult = unknown, TParams = unknown>(\n options: IpcCallOptions<TParams>\n ): Promise<TResult> {\n const response = await this.post<IpcResponse<TResult>>(\n \"/ipc\",\n {\n namespace: options.namespace,\n method: options.method,\n params: options.params ?? {},\n id: options.id ?? createRequestId()\n },\n { timeoutMs: options.timeoutMs }\n );\n\n if (!response.ok) {\n throw new IpcResponseError(response.error);\n }\n\n return response.result;\n }\n\n private async get<TResult>(\n path: string,\n options: IpcRequestOptions = {}\n ): Promise<TResult> {\n return this.request<TResult>(path, {\n method: \"GET\"\n }, options);\n }\n\n private async post<TResult>(\n path: string,\n body: unknown,\n options: IpcRequestOptions = {}\n ): Promise<TResult> {\n return this.request<TResult>(path, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(body)\n }, options);\n }\n\n private async request<TResult>(\n path: string,\n init: RequestInit,\n options: IpcRequestOptions\n ): Promise<TResult> {\n const timeoutMs = options.timeoutMs ?? this.requestTimeoutMs;\n const controller = new AbortController();\n const timeoutError = new IpcTimeoutError(timeoutMs);\n const timeout = setTimeout(() => controller.abort(timeoutError), timeoutMs);\n\n try {\n const response = await this.fetchImpl(`${this.baseUrl}${path}`, {\n ...init,\n signal: controller.signal\n });\n\n if (!response.ok) {\n const text = await response.text();\n const responseError = parseIpcResponseError(text);\n if (responseError) throw new IpcResponseError(responseError);\n throw new IpcHttpError(response.status, text || response.statusText);\n }\n\n return (await response.json()) as TResult;\n } catch (error) {\n if (error instanceof IpcHttpError || error instanceof IpcResponseError) throw error;\n if (controller.signal.aborted) {\n if (error === timeoutError) throw timeoutError;\n throw new IpcTimeoutError(timeoutMs, { cause: error });\n }\n throw new IpcConnectionError(getErrorMessage(error), { cause: error });\n } finally {\n clearTimeout(timeout);\n }\n }\n}\n\nexport class AdofaiIpcNamespaceClient {\n constructor(\n private readonly client: AdofaiIpcClient,\n readonly namespace: string\n ) {\n }\n\n async call<TResult = unknown, TParams = unknown>(\n method: string,\n params?: TParams,\n idOrOptions?: IpcRequestId | IpcRequestOptions,\n options: IpcRequestOptions = {}\n ): Promise<TResult> {\n const requestOptions = isIpcRequestOptions(idOrOptions) ? idOrOptions : options;\n const id = isIpcRequestOptions(idOrOptions) ? undefined : idOrOptions;\n\n return this.client.call<TResult, TParams>({\n namespace: this.namespace,\n method,\n params,\n id,\n timeoutMs: requestOptions.timeoutMs\n });\n }\n}\n\nexport async function tryConnect(options: TryConnectOptions = {}): Promise<AdofaiIpcClient> {\n const host = options.host ?? DEFAULT_HOST;\n const startPort = options.startPort ?? DEFAULT_START_PORT;\n const endPort = options.endPort ?? DEFAULT_END_PORT;\n const probeTimeoutMs =\n options.probeTimeoutMs ?? options.timeoutMs ?? DEFAULT_PROBE_TIMEOUT_MS;\n const requestTimeoutMs =\n options.requestTimeoutMs ?? options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n\n for (let port = startPort; port <= endPort; port++) {\n const client = new AdofaiIpcClient({\n baseUrl: `http://${host}:${port}`,\n fetch: options.fetch,\n requestTimeoutMs: probeTimeoutMs\n });\n\n try {\n const health = await client.health();\n\n if (health.ok && health.server === \"AdofaiIpc\") {\n return new AdofaiIpcClient({\n baseUrl: client.baseUrl,\n fetch: options.fetch,\n requestTimeoutMs\n });\n }\n } catch {\n }\n }\n\n throw new IpcConnectionError(\n `Could not connect to AdofaiIpc on ${host}:${startPort}-${endPort}.`\n );\n}\n\nfunction normalizeBaseUrl(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n\nfunction getErrorMessage(error: unknown): string | undefined {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n return error.message;\n }\n\n return undefined;\n}\n\nfunction parseIpcResponseError(text: string): IpcErrorInfo | undefined {\n try {\n const value = JSON.parse(text) as { error?: unknown };\n const error = value?.error;\n\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n typeof error.code === \"string\" &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n return { code: error.code, message: error.message };\n }\n } catch {\n }\n\n return undefined;\n}\n\nfunction isIpcRequestOptions(value: unknown): value is IpcRequestOptions {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction delay(timeoutMs: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, timeoutMs));\n}\n\nfunction createRequestId(): string {\n return `adofai-ipc-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/errors.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["export {\n AdofaiIpcClient,\n AdofaiIpcNamespaceClient,\n tryConnect\n} from \"./client\";\n\nexport {\n AdofaiIpcError,\n IpcConnectionError,\n IpcHttpError,\n IpcResponseError,\n IpcTimeoutError,\n IpcVersionMismatchError,\n isIpcUnavailable\n} from \"./errors\";\n\nexport type {\n IpcConnectionErrorCode,\n IpcConnectionErrorOptions,\n IpcVersionMismatchDirection\n} from \"./errors\";\n\nexport { CLIENT_VERSION } from \"./version\";\n\nexport type {\n AdofaiIpcClientOptions,\n IpcCallOptions,\n IpcErrorInfo,\n IpcErrorResponse,\n IpcHealthResponse,\n IpcNamespaceDetail,\n IpcNamespaceErrorInfo,\n IpcNamespaceStatus,\n IpcNamespacesResponse,\n IpcNamespaceSummary,\n IpcRequestId,\n IpcRequestOptions,\n IpcResponse,\n IpcSuccessResponse,\n TryConnectOptions,\n WaitForNamespaceOptions\n} from \"./types\";\n","import type { IpcErrorInfo } from \"./types\";\n\nexport type IpcConnectionErrorCode = \"UNAVAILABLE\" | \"TIMEOUT\";\nexport type IpcVersionMismatchDirection =\n | \"server_outdated\"\n | \"client_outdated\"\n | \"legacy_server\";\n\nexport interface IpcConnectionErrorOptions {\n code?: IpcConnectionErrorCode;\n cause?: unknown;\n}\n\nexport class AdofaiIpcError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"AdofaiIpcError\";\n }\n}\n\nexport class IpcConnectionError extends AdofaiIpcError {\n readonly code: IpcConnectionErrorCode;\n readonly cause?: unknown;\n\n constructor(\n message = \"Could not connect to AdofaiIpc.\",\n options: IpcConnectionErrorOptions = {}\n ) {\n super(message);\n this.name = \"IpcConnectionError\";\n this.code = options.code ?? \"UNAVAILABLE\";\n this.cause = options.cause;\n }\n}\n\nexport class IpcTimeoutError extends IpcConnectionError {\n readonly timeoutMs: number;\n\n constructor(timeoutMs: number, options: Pick<IpcConnectionErrorOptions, \"cause\"> = {}) {\n super(`AdofaiIpc request timed out after ${timeoutMs} ms.`, {\n code: \"TIMEOUT\",\n cause: options.cause\n });\n this.name = \"IpcTimeoutError\";\n this.timeoutMs = timeoutMs;\n }\n}\n\nexport class IpcVersionMismatchError extends AdofaiIpcError {\n readonly code = \"VERSION_MISMATCH\" as const;\n readonly clientVersion: string;\n readonly serverVersion: string | null;\n readonly direction: IpcVersionMismatchDirection;\n readonly protocolVersion: number | null;\n\n constructor(options: {\n clientVersion: string;\n serverVersion: string | null;\n direction: IpcVersionMismatchDirection;\n protocolVersion: number | null;\n }) {\n const server = options.serverVersion ?? \"legacy/unknown\";\n super(`AdofaiIpc version mismatch: client ${options.clientVersion}, server ${server}.`);\n this.name = \"IpcVersionMismatchError\";\n this.clientVersion = options.clientVersion;\n this.serverVersion = options.serverVersion;\n this.direction = options.direction;\n this.protocolVersion = options.protocolVersion;\n }\n}\n\nexport function isIpcUnavailable(error: unknown): error is IpcConnectionError {\n return error instanceof IpcConnectionError && error.code === \"UNAVAILABLE\";\n}\n\nexport class IpcHttpError extends AdofaiIpcError {\n readonly status: number;\n\n constructor(status: number, message: string) {\n super(message);\n this.name = \"IpcHttpError\";\n this.status = status;\n }\n}\n\nexport class IpcResponseError extends AdofaiIpcError {\n readonly code: string;\n readonly error: IpcErrorInfo;\n\n constructor(error: IpcErrorInfo) {\n super(error.message);\n this.name = \"IpcResponseError\";\n this.code = error.code;\n this.error = error;\n }\n}\n","declare const __CLIENT_VERSION__: string;\n\nexport const CLIENT_VERSION = __CLIENT_VERSION__;\n\nconst CANONICAL_SEMVER = /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*))*))?$/;\n\ninterface ParsedVersion {\n core: [number, number, number];\n prerelease: string[] | null;\n}\n\nexport function compareProductVersions(left: string, right: string): number | null {\n const leftVersion = parseProductVersion(left);\n const rightVersion = parseProductVersion(right);\n if (!leftVersion || !rightVersion) return null;\n\n for (let index = 0; index < leftVersion.core.length; index++) {\n const difference = leftVersion.core[index]! - rightVersion.core[index]!;\n if (difference !== 0) return difference < 0 ? -1 : 1;\n }\n\n if (leftVersion.prerelease === null) return rightVersion.prerelease === null ? 0 : 1;\n if (rightVersion.prerelease === null) return -1;\n\n const length = Math.max(leftVersion.prerelease.length, rightVersion.prerelease.length);\n for (let index = 0; index < length; index++) {\n const leftPart = leftVersion.prerelease[index];\n const rightPart = rightVersion.prerelease[index];\n if (leftPart === undefined) return -1;\n if (rightPart === undefined) return 1;\n if (leftPart === rightPart) continue;\n\n const leftNumeric = /^\\d+$/.test(leftPart);\n const rightNumeric = /^\\d+$/.test(rightPart);\n if (leftNumeric && rightNumeric) return Number(leftPart) < Number(rightPart) ? -1 : 1;\n if (leftNumeric !== rightNumeric) return leftNumeric ? -1 : 1;\n return leftPart < rightPart ? -1 : 1;\n }\n\n return 0;\n}\n\nfunction parseProductVersion(value: string): ParsedVersion | null {\n const match = CANONICAL_SEMVER.exec(value);\n if (!match) return null;\n return {\n core: [Number(match[1]), Number(match[2]), Number(match[3])],\n prerelease: match[4] ? match[4].split(\".\") : null\n };\n}\n","import {\n IpcConnectionError,\n IpcHttpError,\n IpcResponseError,\n IpcTimeoutError,\n IpcVersionMismatchError\n} from \"./errors\";\nimport { CLIENT_VERSION, compareProductVersions } from \"./version\";\nimport type {\n AdofaiIpcClientOptions,\n IpcCallOptions,\n IpcErrorInfo,\n IpcHealthResponse,\n IpcNamespaceDetail,\n IpcNamespacesResponse,\n IpcRequestId,\n IpcRequestOptions,\n IpcResponse,\n TryConnectOptions,\n WaitForNamespaceOptions\n} from \"./types\";\n\nconst DEFAULT_HOST = \"127.0.0.1\";\nconst DEFAULT_START_PORT = 32145;\nconst DEFAULT_END_PORT = 32155;\nconst DEFAULT_PROBE_TIMEOUT_MS = 500;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 10_000;\nconst DEFAULT_NAMESPACE_WAIT_TIMEOUT_MS = 10_000;\nconst DEFAULT_NAMESPACE_POLL_INTERVAL_MS = 100;\n\nexport class AdofaiIpcClient {\n readonly baseUrl: string;\n\n private readonly fetchImpl: typeof fetch;\n private readonly requestTimeoutMs: number;\n\n constructor(options: AdofaiIpcClientOptions = {}) {\n this.baseUrl = normalizeBaseUrl(options.baseUrl ?? `http://${DEFAULT_HOST}:${DEFAULT_START_PORT}`);\n this.fetchImpl = options.fetch ?? globalThis.fetch;\n this.requestTimeoutMs =\n options.requestTimeoutMs ?? options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n\n if (!this.fetchImpl) {\n throw new IpcConnectionError(\"A fetch implementation is required.\");\n }\n }\n\n static async connect(options: TryConnectOptions = {}): Promise<AdofaiIpcClient> {\n return tryConnect(options);\n }\n\n async health(options: IpcRequestOptions = {}): Promise<IpcHealthResponse> {\n return this.get<IpcHealthResponse>(\"/ipc/health\", options);\n }\n\n async listNamespaces(options: IpcRequestOptions = {}): Promise<IpcNamespacesResponse> {\n return this.get<IpcNamespacesResponse>(\"/ipc/namespaces\", options);\n }\n\n async getNamespace(\n namespace: string,\n options: IpcRequestOptions = {}\n ): Promise<IpcNamespaceDetail> {\n return this.get<IpcNamespaceDetail>(\n `/ipc/namespaces/${encodeURIComponent(namespace)}`,\n options\n );\n }\n\n async waitForNamespace(\n namespace: string,\n options: WaitForNamespaceOptions = {}\n ): Promise<IpcNamespaceDetail> {\n const timeoutMs = options.timeoutMs ?? DEFAULT_NAMESPACE_WAIT_TIMEOUT_MS;\n const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_NAMESPACE_POLL_INTERVAL_MS;\n const requiredStatus = options.status ?? \"registered\";\n const deadline = Date.now() + timeoutMs;\n let stateError: IpcResponseError | undefined;\n\n while (true) {\n try {\n const detail = await this.getNamespace(namespace, {\n timeoutMs: options.requestTimeoutMs\n });\n\n if (requiredStatus === \"registered\" || detail.status === \"ready\") {\n return detail;\n }\n\n if (detail.status === \"error\") {\n throw new IpcResponseError({\n code: \"namespace_error\",\n message: detail.error?.message ?? `Namespace initialization failed: ${namespace}`\n });\n }\n\n if (detail.status !== \"initializing\") {\n throw new IpcResponseError({\n code: \"namespace_status_unavailable\",\n message: `Namespace status is unavailable: ${namespace}`\n });\n }\n\n stateError = new IpcResponseError({\n code: \"namespace_initializing\",\n message: `Namespace is initializing: ${namespace}`\n });\n } catch (error) {\n if (\n !(error instanceof IpcResponseError) ||\n (error.code !== \"namespace_not_found\" && error.code !== \"namespace_initializing\")\n ) {\n throw error;\n }\n\n stateError = error;\n }\n\n const remainingMs = deadline - Date.now();\n if (remainingMs <= 0) {\n throw stateError ?? new IpcResponseError({\n code: \"namespace_initializing\",\n message: `Namespace is initializing: ${namespace}`\n });\n }\n\n await delay(Math.min(pollIntervalMs, remainingMs));\n }\n }\n\n namespace(namespace: string): AdofaiIpcNamespaceClient {\n return new AdofaiIpcNamespaceClient(this, namespace);\n }\n\n async call<TResult = unknown, TParams = unknown>(\n options: IpcCallOptions<TParams>\n ): Promise<TResult> {\n const response = await this.post<IpcResponse<TResult>>(\n \"/ipc\",\n {\n namespace: options.namespace,\n method: options.method,\n params: options.params ?? {},\n id: options.id ?? createRequestId()\n },\n { timeoutMs: options.timeoutMs }\n );\n\n if (!response.ok) {\n throw new IpcResponseError(response.error);\n }\n\n return response.result;\n }\n\n private async get<TResult>(\n path: string,\n options: IpcRequestOptions = {}\n ): Promise<TResult> {\n return this.request<TResult>(path, {\n method: \"GET\"\n }, options);\n }\n\n private async post<TResult>(\n path: string,\n body: unknown,\n options: IpcRequestOptions = {}\n ): Promise<TResult> {\n return this.request<TResult>(path, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(body)\n }, options);\n }\n\n private async request<TResult>(\n path: string,\n init: RequestInit,\n options: IpcRequestOptions\n ): Promise<TResult> {\n const timeoutMs = options.timeoutMs ?? this.requestTimeoutMs;\n const controller = new AbortController();\n const timeoutError = new IpcTimeoutError(timeoutMs);\n const timeout = setTimeout(() => controller.abort(timeoutError), timeoutMs);\n\n try {\n const response = await this.fetchImpl(`${this.baseUrl}${path}`, {\n ...init,\n signal: controller.signal\n });\n\n if (!response.ok) {\n const text = await response.text();\n const responseError = parseIpcResponseError(text);\n if (responseError) throw new IpcResponseError(responseError);\n throw new IpcHttpError(response.status, text || response.statusText);\n }\n\n return (await response.json()) as TResult;\n } catch (error) {\n if (error instanceof IpcHttpError || error instanceof IpcResponseError) throw error;\n if (controller.signal.aborted) {\n if (error === timeoutError) throw timeoutError;\n throw new IpcTimeoutError(timeoutMs, { cause: error });\n }\n throw new IpcConnectionError(getErrorMessage(error), { cause: error });\n } finally {\n clearTimeout(timeout);\n }\n }\n}\n\nexport class AdofaiIpcNamespaceClient {\n constructor(\n private readonly client: AdofaiIpcClient,\n readonly namespace: string\n ) {\n }\n\n async call<TResult = unknown, TParams = unknown>(\n method: string,\n params?: TParams,\n idOrOptions?: IpcRequestId | IpcRequestOptions,\n options: IpcRequestOptions = {}\n ): Promise<TResult> {\n const requestOptions = isIpcRequestOptions(idOrOptions) ? idOrOptions : options;\n const id = isIpcRequestOptions(idOrOptions) ? undefined : idOrOptions;\n\n return this.client.call<TResult, TParams>({\n namespace: this.namespace,\n method,\n params,\n id,\n timeoutMs: requestOptions.timeoutMs\n });\n }\n}\n\nexport async function tryConnect(options: TryConnectOptions = {}): Promise<AdofaiIpcClient> {\n const host = options.host ?? DEFAULT_HOST;\n const startPort = options.startPort ?? DEFAULT_START_PORT;\n const endPort = options.endPort ?? DEFAULT_END_PORT;\n const probeTimeoutMs =\n options.probeTimeoutMs ?? options.timeoutMs ?? DEFAULT_PROBE_TIMEOUT_MS;\n const requestTimeoutMs =\n options.requestTimeoutMs ?? options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n let lastProbeError: unknown;\n\n for (let port = startPort; port <= endPort; port++) {\n const client = new AdofaiIpcClient({\n baseUrl: `http://${host}:${port}`,\n fetch: options.fetch,\n requestTimeoutMs: probeTimeoutMs\n });\n\n try {\n const health = await client.health();\n\n if (health.ok && health.server === \"AdofaiIpc\") {\n const mismatch = getVersionMismatch(health);\n if (mismatch) {\n try {\n options.onVersionMismatch?.(mismatch);\n } catch {\n }\n throw mismatch;\n }\n return new AdofaiIpcClient({\n baseUrl: client.baseUrl,\n fetch: options.fetch,\n requestTimeoutMs\n });\n }\n } catch (error) {\n if (error instanceof IpcVersionMismatchError) throw error;\n lastProbeError = error;\n }\n }\n\n if (lastProbeError instanceof IpcTimeoutError) throw lastProbeError;\n\n throw new IpcConnectionError(\n `Could not connect to AdofaiIpc on ${host}:${startPort}-${endPort}.`\n );\n}\n\nfunction getVersionMismatch(health: IpcHealthResponse): IpcVersionMismatchError | null {\n const protocolVersion = Number.isInteger(health.protocolVersion) ? health.protocolVersion : null;\n const serverVersion = typeof health.serverVersion === \"string\" ? health.serverVersion : null;\n const comparison = serverVersion === null\n ? null\n : compareProductVersions(serverVersion, CLIENT_VERSION);\n\n if (comparison === 0 && serverVersion === CLIENT_VERSION) return null;\n\n return new IpcVersionMismatchError({\n clientVersion: CLIENT_VERSION,\n serverVersion,\n direction: comparison === null\n ? \"legacy_server\"\n : comparison < 0\n ? \"server_outdated\"\n : \"client_outdated\",\n protocolVersion\n });\n}\n\nfunction normalizeBaseUrl(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n\nfunction getErrorMessage(error: unknown): string | undefined {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n return error.message;\n }\n\n return undefined;\n}\n\nfunction parseIpcResponseError(text: string): IpcErrorInfo | undefined {\n try {\n const value = JSON.parse(text) as { error?: unknown };\n const error = value?.error;\n\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n typeof error.code === \"string\" &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n return { code: error.code, message: error.message };\n }\n } catch {\n }\n\n return undefined;\n}\n\nfunction isIpcRequestOptions(value: unknown): value is IpcRequestOptions {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction delay(timeoutMs: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, timeoutMs));\n}\n\nfunction createRequestId(): string {\n return `adofai-ipc-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n}\n"],"mappings":"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","names":[]}
package/dist/index.d.cts CHANGED
@@ -1,3 +1,45 @@
1
+ type IpcConnectionErrorCode = "UNAVAILABLE" | "TIMEOUT";
2
+ type IpcVersionMismatchDirection = "server_outdated" | "client_outdated" | "legacy_server";
3
+ interface IpcConnectionErrorOptions {
4
+ code?: IpcConnectionErrorCode;
5
+ cause?: unknown;
6
+ }
7
+ declare class AdofaiIpcError extends Error {
8
+ constructor(message: string);
9
+ }
10
+ declare class IpcConnectionError extends AdofaiIpcError {
11
+ readonly code: IpcConnectionErrorCode;
12
+ readonly cause?: unknown;
13
+ constructor(message?: string, options?: IpcConnectionErrorOptions);
14
+ }
15
+ declare class IpcTimeoutError extends IpcConnectionError {
16
+ readonly timeoutMs: number;
17
+ constructor(timeoutMs: number, options?: Pick<IpcConnectionErrorOptions, "cause">);
18
+ }
19
+ declare class IpcVersionMismatchError extends AdofaiIpcError {
20
+ readonly code: "VERSION_MISMATCH";
21
+ readonly clientVersion: string;
22
+ readonly serverVersion: string | null;
23
+ readonly direction: IpcVersionMismatchDirection;
24
+ readonly protocolVersion: number | null;
25
+ constructor(options: {
26
+ clientVersion: string;
27
+ serverVersion: string | null;
28
+ direction: IpcVersionMismatchDirection;
29
+ protocolVersion: number | null;
30
+ });
31
+ }
32
+ declare function isIpcUnavailable(error: unknown): error is IpcConnectionError;
33
+ declare class IpcHttpError extends AdofaiIpcError {
34
+ readonly status: number;
35
+ constructor(status: number, message: string);
36
+ }
37
+ declare class IpcResponseError extends AdofaiIpcError {
38
+ readonly code: string;
39
+ readonly error: IpcErrorInfo;
40
+ constructor(error: IpcErrorInfo);
41
+ }
42
+
1
43
  type IpcRequestId = string | number | null;
2
44
  interface IpcCallOptions<TParams = unknown> {
3
45
  namespace: string;
@@ -34,6 +76,7 @@ type IpcResponse<TResult = unknown> = IpcSuccessResponse<TResult> | IpcErrorResp
34
76
  interface IpcHealthResponse {
35
77
  ok: true;
36
78
  server: "AdofaiIpc";
79
+ serverVersion?: string;
37
80
  protocolVersion: number;
38
81
  port: number;
39
82
  }
@@ -73,6 +116,7 @@ interface TryConnectOptions {
73
116
  fetch?: typeof fetch;
74
117
  probeTimeoutMs?: number;
75
118
  requestTimeoutMs?: number;
119
+ onVersionMismatch?: (error: IpcVersionMismatchError) => void;
76
120
  /** @deprecated Use probeTimeoutMs and requestTimeoutMs instead. */
77
121
  timeoutMs?: number;
78
122
  }
@@ -101,32 +145,6 @@ declare class AdofaiIpcNamespaceClient {
101
145
  }
102
146
  declare function tryConnect(options?: TryConnectOptions): Promise<AdofaiIpcClient>;
103
147
 
104
- type IpcConnectionErrorCode = "UNAVAILABLE" | "TIMEOUT";
105
- interface IpcConnectionErrorOptions {
106
- code?: IpcConnectionErrorCode;
107
- cause?: unknown;
108
- }
109
- declare class AdofaiIpcError extends Error {
110
- constructor(message: string);
111
- }
112
- declare class IpcConnectionError extends AdofaiIpcError {
113
- readonly code: IpcConnectionErrorCode;
114
- readonly cause?: unknown;
115
- constructor(message?: string, options?: IpcConnectionErrorOptions);
116
- }
117
- declare class IpcTimeoutError extends IpcConnectionError {
118
- readonly timeoutMs: number;
119
- constructor(timeoutMs: number, options?: Pick<IpcConnectionErrorOptions, "cause">);
120
- }
121
- declare function isIpcUnavailable(error: unknown): error is IpcConnectionError;
122
- declare class IpcHttpError extends AdofaiIpcError {
123
- readonly status: number;
124
- constructor(status: number, message: string);
125
- }
126
- declare class IpcResponseError extends AdofaiIpcError {
127
- readonly code: string;
128
- readonly error: IpcErrorInfo;
129
- constructor(error: IpcErrorInfo);
130
- }
148
+ declare const CLIENT_VERSION: string;
131
149
 
132
- export { AdofaiIpcClient, type AdofaiIpcClientOptions, AdofaiIpcError, AdofaiIpcNamespaceClient, type IpcCallOptions, IpcConnectionError, type IpcConnectionErrorCode, type IpcConnectionErrorOptions, type IpcErrorInfo, type IpcErrorResponse, type IpcHealthResponse, IpcHttpError, type IpcNamespaceDetail, type IpcNamespaceErrorInfo, type IpcNamespaceStatus, type IpcNamespaceSummary, type IpcNamespacesResponse, type IpcRequestId, type IpcRequestOptions, type IpcResponse, IpcResponseError, type IpcSuccessResponse, IpcTimeoutError, type TryConnectOptions, type WaitForNamespaceOptions, isIpcUnavailable, tryConnect };
150
+ export { AdofaiIpcClient, type AdofaiIpcClientOptions, AdofaiIpcError, AdofaiIpcNamespaceClient, CLIENT_VERSION, type IpcCallOptions, IpcConnectionError, type IpcConnectionErrorCode, type IpcConnectionErrorOptions, type IpcErrorInfo, type IpcErrorResponse, type IpcHealthResponse, IpcHttpError, type IpcNamespaceDetail, type IpcNamespaceErrorInfo, type IpcNamespaceStatus, type IpcNamespaceSummary, type IpcNamespacesResponse, type IpcRequestId, type IpcRequestOptions, type IpcResponse, IpcResponseError, type IpcSuccessResponse, IpcTimeoutError, type IpcVersionMismatchDirection, IpcVersionMismatchError, type TryConnectOptions, type WaitForNamespaceOptions, isIpcUnavailable, tryConnect };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,45 @@
1
+ type IpcConnectionErrorCode = "UNAVAILABLE" | "TIMEOUT";
2
+ type IpcVersionMismatchDirection = "server_outdated" | "client_outdated" | "legacy_server";
3
+ interface IpcConnectionErrorOptions {
4
+ code?: IpcConnectionErrorCode;
5
+ cause?: unknown;
6
+ }
7
+ declare class AdofaiIpcError extends Error {
8
+ constructor(message: string);
9
+ }
10
+ declare class IpcConnectionError extends AdofaiIpcError {
11
+ readonly code: IpcConnectionErrorCode;
12
+ readonly cause?: unknown;
13
+ constructor(message?: string, options?: IpcConnectionErrorOptions);
14
+ }
15
+ declare class IpcTimeoutError extends IpcConnectionError {
16
+ readonly timeoutMs: number;
17
+ constructor(timeoutMs: number, options?: Pick<IpcConnectionErrorOptions, "cause">);
18
+ }
19
+ declare class IpcVersionMismatchError extends AdofaiIpcError {
20
+ readonly code: "VERSION_MISMATCH";
21
+ readonly clientVersion: string;
22
+ readonly serverVersion: string | null;
23
+ readonly direction: IpcVersionMismatchDirection;
24
+ readonly protocolVersion: number | null;
25
+ constructor(options: {
26
+ clientVersion: string;
27
+ serverVersion: string | null;
28
+ direction: IpcVersionMismatchDirection;
29
+ protocolVersion: number | null;
30
+ });
31
+ }
32
+ declare function isIpcUnavailable(error: unknown): error is IpcConnectionError;
33
+ declare class IpcHttpError extends AdofaiIpcError {
34
+ readonly status: number;
35
+ constructor(status: number, message: string);
36
+ }
37
+ declare class IpcResponseError extends AdofaiIpcError {
38
+ readonly code: string;
39
+ readonly error: IpcErrorInfo;
40
+ constructor(error: IpcErrorInfo);
41
+ }
42
+
1
43
  type IpcRequestId = string | number | null;
2
44
  interface IpcCallOptions<TParams = unknown> {
3
45
  namespace: string;
@@ -34,6 +76,7 @@ type IpcResponse<TResult = unknown> = IpcSuccessResponse<TResult> | IpcErrorResp
34
76
  interface IpcHealthResponse {
35
77
  ok: true;
36
78
  server: "AdofaiIpc";
79
+ serverVersion?: string;
37
80
  protocolVersion: number;
38
81
  port: number;
39
82
  }
@@ -73,6 +116,7 @@ interface TryConnectOptions {
73
116
  fetch?: typeof fetch;
74
117
  probeTimeoutMs?: number;
75
118
  requestTimeoutMs?: number;
119
+ onVersionMismatch?: (error: IpcVersionMismatchError) => void;
76
120
  /** @deprecated Use probeTimeoutMs and requestTimeoutMs instead. */
77
121
  timeoutMs?: number;
78
122
  }
@@ -101,32 +145,6 @@ declare class AdofaiIpcNamespaceClient {
101
145
  }
102
146
  declare function tryConnect(options?: TryConnectOptions): Promise<AdofaiIpcClient>;
103
147
 
104
- type IpcConnectionErrorCode = "UNAVAILABLE" | "TIMEOUT";
105
- interface IpcConnectionErrorOptions {
106
- code?: IpcConnectionErrorCode;
107
- cause?: unknown;
108
- }
109
- declare class AdofaiIpcError extends Error {
110
- constructor(message: string);
111
- }
112
- declare class IpcConnectionError extends AdofaiIpcError {
113
- readonly code: IpcConnectionErrorCode;
114
- readonly cause?: unknown;
115
- constructor(message?: string, options?: IpcConnectionErrorOptions);
116
- }
117
- declare class IpcTimeoutError extends IpcConnectionError {
118
- readonly timeoutMs: number;
119
- constructor(timeoutMs: number, options?: Pick<IpcConnectionErrorOptions, "cause">);
120
- }
121
- declare function isIpcUnavailable(error: unknown): error is IpcConnectionError;
122
- declare class IpcHttpError extends AdofaiIpcError {
123
- readonly status: number;
124
- constructor(status: number, message: string);
125
- }
126
- declare class IpcResponseError extends AdofaiIpcError {
127
- readonly code: string;
128
- readonly error: IpcErrorInfo;
129
- constructor(error: IpcErrorInfo);
130
- }
148
+ declare const CLIENT_VERSION: string;
131
149
 
132
- export { AdofaiIpcClient, type AdofaiIpcClientOptions, AdofaiIpcError, AdofaiIpcNamespaceClient, type IpcCallOptions, IpcConnectionError, type IpcConnectionErrorCode, type IpcConnectionErrorOptions, type IpcErrorInfo, type IpcErrorResponse, type IpcHealthResponse, IpcHttpError, type IpcNamespaceDetail, type IpcNamespaceErrorInfo, type IpcNamespaceStatus, type IpcNamespaceSummary, type IpcNamespacesResponse, type IpcRequestId, type IpcRequestOptions, type IpcResponse, IpcResponseError, type IpcSuccessResponse, IpcTimeoutError, type TryConnectOptions, type WaitForNamespaceOptions, isIpcUnavailable, tryConnect };
150
+ export { AdofaiIpcClient, type AdofaiIpcClientOptions, AdofaiIpcError, AdofaiIpcNamespaceClient, CLIENT_VERSION, type IpcCallOptions, IpcConnectionError, type IpcConnectionErrorCode, type IpcConnectionErrorOptions, type IpcErrorInfo, type IpcErrorResponse, type IpcHealthResponse, IpcHttpError, type IpcNamespaceDetail, type IpcNamespaceErrorInfo, type IpcNamespaceStatus, type IpcNamespaceSummary, type IpcNamespacesResponse, type IpcRequestId, type IpcRequestOptions, type IpcResponse, IpcResponseError, type IpcSuccessResponse, IpcTimeoutError, type IpcVersionMismatchDirection, IpcVersionMismatchError, type TryConnectOptions, type WaitForNamespaceOptions, isIpcUnavailable, tryConnect };
package/dist/index.js CHANGED
@@ -23,6 +23,18 @@ var IpcTimeoutError = class extends IpcConnectionError {
23
23
  this.timeoutMs = timeoutMs;
24
24
  }
25
25
  };
26
+ var IpcVersionMismatchError = class extends AdofaiIpcError {
27
+ constructor(options) {
28
+ const server = options.serverVersion ?? "legacy/unknown";
29
+ super(`AdofaiIpc version mismatch: client ${options.clientVersion}, server ${server}.`);
30
+ this.code = "VERSION_MISMATCH";
31
+ this.name = "IpcVersionMismatchError";
32
+ this.clientVersion = options.clientVersion;
33
+ this.serverVersion = options.serverVersion;
34
+ this.direction = options.direction;
35
+ this.protocolVersion = options.protocolVersion;
36
+ }
37
+ };
26
38
  function isIpcUnavailable(error) {
27
39
  return error instanceof IpcConnectionError && error.code === "UNAVAILABLE";
28
40
  }
@@ -42,6 +54,43 @@ var IpcResponseError = class extends AdofaiIpcError {
42
54
  }
43
55
  };
44
56
 
57
+ // src/version.ts
58
+ var CLIENT_VERSION = "0.4.0";
59
+ var CANONICAL_SEMVER = /^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?$/;
60
+ function compareProductVersions(left, right) {
61
+ const leftVersion = parseProductVersion(left);
62
+ const rightVersion = parseProductVersion(right);
63
+ if (!leftVersion || !rightVersion) return null;
64
+ for (let index = 0; index < leftVersion.core.length; index++) {
65
+ const difference = leftVersion.core[index] - rightVersion.core[index];
66
+ if (difference !== 0) return difference < 0 ? -1 : 1;
67
+ }
68
+ if (leftVersion.prerelease === null) return rightVersion.prerelease === null ? 0 : 1;
69
+ if (rightVersion.prerelease === null) return -1;
70
+ const length = Math.max(leftVersion.prerelease.length, rightVersion.prerelease.length);
71
+ for (let index = 0; index < length; index++) {
72
+ const leftPart = leftVersion.prerelease[index];
73
+ const rightPart = rightVersion.prerelease[index];
74
+ if (leftPart === void 0) return -1;
75
+ if (rightPart === void 0) return 1;
76
+ if (leftPart === rightPart) continue;
77
+ const leftNumeric = /^\d+$/.test(leftPart);
78
+ const rightNumeric = /^\d+$/.test(rightPart);
79
+ if (leftNumeric && rightNumeric) return Number(leftPart) < Number(rightPart) ? -1 : 1;
80
+ if (leftNumeric !== rightNumeric) return leftNumeric ? -1 : 1;
81
+ return leftPart < rightPart ? -1 : 1;
82
+ }
83
+ return 0;
84
+ }
85
+ function parseProductVersion(value) {
86
+ const match = CANONICAL_SEMVER.exec(value);
87
+ if (!match) return null;
88
+ return {
89
+ core: [Number(match[1]), Number(match[2]), Number(match[3])],
90
+ prerelease: match[4] ? match[4].split(".") : null
91
+ };
92
+ }
93
+
45
94
  // src/client.ts
46
95
  var DEFAULT_HOST = "127.0.0.1";
47
96
  var DEFAULT_START_PORT = 32145;
@@ -205,6 +254,7 @@ async function tryConnect(options = {}) {
205
254
  const endPort = options.endPort ?? DEFAULT_END_PORT;
206
255
  const probeTimeoutMs = options.probeTimeoutMs ?? options.timeoutMs ?? DEFAULT_PROBE_TIMEOUT_MS;
207
256
  const requestTimeoutMs = options.requestTimeoutMs ?? options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;
257
+ let lastProbeError;
208
258
  for (let port = startPort; port <= endPort; port++) {
209
259
  const client = new AdofaiIpcClient({
210
260
  baseUrl: `http://${host}:${port}`,
@@ -214,19 +264,42 @@ async function tryConnect(options = {}) {
214
264
  try {
215
265
  const health = await client.health();
216
266
  if (health.ok && health.server === "AdofaiIpc") {
267
+ const mismatch = getVersionMismatch(health);
268
+ if (mismatch) {
269
+ try {
270
+ options.onVersionMismatch?.(mismatch);
271
+ } catch {
272
+ }
273
+ throw mismatch;
274
+ }
217
275
  return new AdofaiIpcClient({
218
276
  baseUrl: client.baseUrl,
219
277
  fetch: options.fetch,
220
278
  requestTimeoutMs
221
279
  });
222
280
  }
223
- } catch {
281
+ } catch (error) {
282
+ if (error instanceof IpcVersionMismatchError) throw error;
283
+ lastProbeError = error;
224
284
  }
225
285
  }
286
+ if (lastProbeError instanceof IpcTimeoutError) throw lastProbeError;
226
287
  throw new IpcConnectionError(
227
288
  `Could not connect to AdofaiIpc on ${host}:${startPort}-${endPort}.`
228
289
  );
229
290
  }
291
+ function getVersionMismatch(health) {
292
+ const protocolVersion = Number.isInteger(health.protocolVersion) ? health.protocolVersion : null;
293
+ const serverVersion = typeof health.serverVersion === "string" ? health.serverVersion : null;
294
+ const comparison = serverVersion === null ? null : compareProductVersions(serverVersion, CLIENT_VERSION);
295
+ if (comparison === 0 && serverVersion === CLIENT_VERSION) return null;
296
+ return new IpcVersionMismatchError({
297
+ clientVersion: CLIENT_VERSION,
298
+ serverVersion,
299
+ direction: comparison === null ? "legacy_server" : comparison < 0 ? "server_outdated" : "client_outdated",
300
+ protocolVersion
301
+ });
302
+ }
230
303
  function normalizeBaseUrl(value) {
231
304
  return value.replace(/\/+$/, "");
232
305
  }
@@ -260,10 +333,12 @@ export {
260
333
  AdofaiIpcClient,
261
334
  AdofaiIpcError,
262
335
  AdofaiIpcNamespaceClient,
336
+ CLIENT_VERSION,
263
337
  IpcConnectionError,
264
338
  IpcHttpError,
265
339
  IpcResponseError,
266
340
  IpcTimeoutError,
341
+ IpcVersionMismatchError,
267
342
  isIpcUnavailable,
268
343
  tryConnect
269
344
  };
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/errors.ts","../src/client.ts"],"sourcesContent":["import type { IpcErrorInfo } from \"./types\";\n\nexport type IpcConnectionErrorCode = \"UNAVAILABLE\" | \"TIMEOUT\";\n\nexport interface IpcConnectionErrorOptions {\n code?: IpcConnectionErrorCode;\n cause?: unknown;\n}\n\nexport class AdofaiIpcError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"AdofaiIpcError\";\n }\n}\n\nexport class IpcConnectionError extends AdofaiIpcError {\n readonly code: IpcConnectionErrorCode;\n readonly cause?: unknown;\n\n constructor(\n message = \"Could not connect to AdofaiIpc.\",\n options: IpcConnectionErrorOptions = {}\n ) {\n super(message);\n this.name = \"IpcConnectionError\";\n this.code = options.code ?? \"UNAVAILABLE\";\n this.cause = options.cause;\n }\n}\n\nexport class IpcTimeoutError extends IpcConnectionError {\n readonly timeoutMs: number;\n\n constructor(timeoutMs: number, options: Pick<IpcConnectionErrorOptions, \"cause\"> = {}) {\n super(`AdofaiIpc request timed out after ${timeoutMs} ms.`, {\n code: \"TIMEOUT\",\n cause: options.cause\n });\n this.name = \"IpcTimeoutError\";\n this.timeoutMs = timeoutMs;\n }\n}\n\nexport function isIpcUnavailable(error: unknown): error is IpcConnectionError {\n return error instanceof IpcConnectionError && error.code === \"UNAVAILABLE\";\n}\n\nexport class IpcHttpError extends AdofaiIpcError {\n readonly status: number;\n\n constructor(status: number, message: string) {\n super(message);\n this.name = \"IpcHttpError\";\n this.status = status;\n }\n}\n\nexport class IpcResponseError extends AdofaiIpcError {\n readonly code: string;\n readonly error: IpcErrorInfo;\n\n constructor(error: IpcErrorInfo) {\n super(error.message);\n this.name = \"IpcResponseError\";\n this.code = error.code;\n this.error = error;\n }\n}\n","import {\n IpcConnectionError,\n IpcHttpError,\n IpcResponseError,\n IpcTimeoutError\n} from \"./errors\";\nimport type {\n AdofaiIpcClientOptions,\n IpcCallOptions,\n IpcErrorInfo,\n IpcHealthResponse,\n IpcNamespaceDetail,\n IpcNamespacesResponse,\n IpcRequestId,\n IpcRequestOptions,\n IpcResponse,\n TryConnectOptions,\n WaitForNamespaceOptions\n} from \"./types\";\n\nconst DEFAULT_HOST = \"127.0.0.1\";\nconst DEFAULT_START_PORT = 32145;\nconst DEFAULT_END_PORT = 32155;\nconst DEFAULT_PROBE_TIMEOUT_MS = 500;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 10_000;\nconst DEFAULT_NAMESPACE_WAIT_TIMEOUT_MS = 10_000;\nconst DEFAULT_NAMESPACE_POLL_INTERVAL_MS = 100;\n\nexport class AdofaiIpcClient {\n readonly baseUrl: string;\n\n private readonly fetchImpl: typeof fetch;\n private readonly requestTimeoutMs: number;\n\n constructor(options: AdofaiIpcClientOptions = {}) {\n this.baseUrl = normalizeBaseUrl(options.baseUrl ?? `http://${DEFAULT_HOST}:${DEFAULT_START_PORT}`);\n this.fetchImpl = options.fetch ?? globalThis.fetch;\n this.requestTimeoutMs =\n options.requestTimeoutMs ?? options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n\n if (!this.fetchImpl) {\n throw new IpcConnectionError(\"A fetch implementation is required.\");\n }\n }\n\n static async connect(options: TryConnectOptions = {}): Promise<AdofaiIpcClient> {\n return tryConnect(options);\n }\n\n async health(options: IpcRequestOptions = {}): Promise<IpcHealthResponse> {\n return this.get<IpcHealthResponse>(\"/ipc/health\", options);\n }\n\n async listNamespaces(options: IpcRequestOptions = {}): Promise<IpcNamespacesResponse> {\n return this.get<IpcNamespacesResponse>(\"/ipc/namespaces\", options);\n }\n\n async getNamespace(\n namespace: string,\n options: IpcRequestOptions = {}\n ): Promise<IpcNamespaceDetail> {\n return this.get<IpcNamespaceDetail>(\n `/ipc/namespaces/${encodeURIComponent(namespace)}`,\n options\n );\n }\n\n async waitForNamespace(\n namespace: string,\n options: WaitForNamespaceOptions = {}\n ): Promise<IpcNamespaceDetail> {\n const timeoutMs = options.timeoutMs ?? DEFAULT_NAMESPACE_WAIT_TIMEOUT_MS;\n const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_NAMESPACE_POLL_INTERVAL_MS;\n const requiredStatus = options.status ?? \"registered\";\n const deadline = Date.now() + timeoutMs;\n let stateError: IpcResponseError | undefined;\n\n while (true) {\n try {\n const detail = await this.getNamespace(namespace, {\n timeoutMs: options.requestTimeoutMs\n });\n\n if (requiredStatus === \"registered\" || detail.status === \"ready\") {\n return detail;\n }\n\n if (detail.status === \"error\") {\n throw new IpcResponseError({\n code: \"namespace_error\",\n message: detail.error?.message ?? `Namespace initialization failed: ${namespace}`\n });\n }\n\n if (detail.status !== \"initializing\") {\n throw new IpcResponseError({\n code: \"namespace_status_unavailable\",\n message: `Namespace status is unavailable: ${namespace}`\n });\n }\n\n stateError = new IpcResponseError({\n code: \"namespace_initializing\",\n message: `Namespace is initializing: ${namespace}`\n });\n } catch (error) {\n if (\n !(error instanceof IpcResponseError) ||\n (error.code !== \"namespace_not_found\" && error.code !== \"namespace_initializing\")\n ) {\n throw error;\n }\n\n stateError = error;\n }\n\n const remainingMs = deadline - Date.now();\n if (remainingMs <= 0) {\n throw stateError ?? new IpcResponseError({\n code: \"namespace_initializing\",\n message: `Namespace is initializing: ${namespace}`\n });\n }\n\n await delay(Math.min(pollIntervalMs, remainingMs));\n }\n }\n\n namespace(namespace: string): AdofaiIpcNamespaceClient {\n return new AdofaiIpcNamespaceClient(this, namespace);\n }\n\n async call<TResult = unknown, TParams = unknown>(\n options: IpcCallOptions<TParams>\n ): Promise<TResult> {\n const response = await this.post<IpcResponse<TResult>>(\n \"/ipc\",\n {\n namespace: options.namespace,\n method: options.method,\n params: options.params ?? {},\n id: options.id ?? createRequestId()\n },\n { timeoutMs: options.timeoutMs }\n );\n\n if (!response.ok) {\n throw new IpcResponseError(response.error);\n }\n\n return response.result;\n }\n\n private async get<TResult>(\n path: string,\n options: IpcRequestOptions = {}\n ): Promise<TResult> {\n return this.request<TResult>(path, {\n method: \"GET\"\n }, options);\n }\n\n private async post<TResult>(\n path: string,\n body: unknown,\n options: IpcRequestOptions = {}\n ): Promise<TResult> {\n return this.request<TResult>(path, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(body)\n }, options);\n }\n\n private async request<TResult>(\n path: string,\n init: RequestInit,\n options: IpcRequestOptions\n ): Promise<TResult> {\n const timeoutMs = options.timeoutMs ?? this.requestTimeoutMs;\n const controller = new AbortController();\n const timeoutError = new IpcTimeoutError(timeoutMs);\n const timeout = setTimeout(() => controller.abort(timeoutError), timeoutMs);\n\n try {\n const response = await this.fetchImpl(`${this.baseUrl}${path}`, {\n ...init,\n signal: controller.signal\n });\n\n if (!response.ok) {\n const text = await response.text();\n const responseError = parseIpcResponseError(text);\n if (responseError) throw new IpcResponseError(responseError);\n throw new IpcHttpError(response.status, text || response.statusText);\n }\n\n return (await response.json()) as TResult;\n } catch (error) {\n if (error instanceof IpcHttpError || error instanceof IpcResponseError) throw error;\n if (controller.signal.aborted) {\n if (error === timeoutError) throw timeoutError;\n throw new IpcTimeoutError(timeoutMs, { cause: error });\n }\n throw new IpcConnectionError(getErrorMessage(error), { cause: error });\n } finally {\n clearTimeout(timeout);\n }\n }\n}\n\nexport class AdofaiIpcNamespaceClient {\n constructor(\n private readonly client: AdofaiIpcClient,\n readonly namespace: string\n ) {\n }\n\n async call<TResult = unknown, TParams = unknown>(\n method: string,\n params?: TParams,\n idOrOptions?: IpcRequestId | IpcRequestOptions,\n options: IpcRequestOptions = {}\n ): Promise<TResult> {\n const requestOptions = isIpcRequestOptions(idOrOptions) ? idOrOptions : options;\n const id = isIpcRequestOptions(idOrOptions) ? undefined : idOrOptions;\n\n return this.client.call<TResult, TParams>({\n namespace: this.namespace,\n method,\n params,\n id,\n timeoutMs: requestOptions.timeoutMs\n });\n }\n}\n\nexport async function tryConnect(options: TryConnectOptions = {}): Promise<AdofaiIpcClient> {\n const host = options.host ?? DEFAULT_HOST;\n const startPort = options.startPort ?? DEFAULT_START_PORT;\n const endPort = options.endPort ?? DEFAULT_END_PORT;\n const probeTimeoutMs =\n options.probeTimeoutMs ?? options.timeoutMs ?? DEFAULT_PROBE_TIMEOUT_MS;\n const requestTimeoutMs =\n options.requestTimeoutMs ?? options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n\n for (let port = startPort; port <= endPort; port++) {\n const client = new AdofaiIpcClient({\n baseUrl: `http://${host}:${port}`,\n fetch: options.fetch,\n requestTimeoutMs: probeTimeoutMs\n });\n\n try {\n const health = await client.health();\n\n if (health.ok && health.server === \"AdofaiIpc\") {\n return new AdofaiIpcClient({\n baseUrl: client.baseUrl,\n fetch: options.fetch,\n requestTimeoutMs\n });\n }\n } catch {\n }\n }\n\n throw new IpcConnectionError(\n `Could not connect to AdofaiIpc on ${host}:${startPort}-${endPort}.`\n );\n}\n\nfunction normalizeBaseUrl(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n\nfunction getErrorMessage(error: unknown): string | undefined {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n return error.message;\n }\n\n return undefined;\n}\n\nfunction parseIpcResponseError(text: string): IpcErrorInfo | undefined {\n try {\n const value = JSON.parse(text) as { error?: unknown };\n const error = value?.error;\n\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n typeof error.code === \"string\" &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n return { code: error.code, message: error.message };\n }\n } catch {\n }\n\n return undefined;\n}\n\nfunction isIpcRequestOptions(value: unknown): value is IpcRequestOptions {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction delay(timeoutMs: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, timeoutMs));\n}\n\nfunction createRequestId(): string {\n return `adofai-ipc-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/errors.ts","../src/version.ts","../src/client.ts"],"sourcesContent":["import type { IpcErrorInfo } from \"./types\";\n\nexport type IpcConnectionErrorCode = \"UNAVAILABLE\" | \"TIMEOUT\";\nexport type IpcVersionMismatchDirection =\n | \"server_outdated\"\n | \"client_outdated\"\n | \"legacy_server\";\n\nexport interface IpcConnectionErrorOptions {\n code?: IpcConnectionErrorCode;\n cause?: unknown;\n}\n\nexport class AdofaiIpcError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"AdofaiIpcError\";\n }\n}\n\nexport class IpcConnectionError extends AdofaiIpcError {\n readonly code: IpcConnectionErrorCode;\n readonly cause?: unknown;\n\n constructor(\n message = \"Could not connect to AdofaiIpc.\",\n options: IpcConnectionErrorOptions = {}\n ) {\n super(message);\n this.name = \"IpcConnectionError\";\n this.code = options.code ?? \"UNAVAILABLE\";\n this.cause = options.cause;\n }\n}\n\nexport class IpcTimeoutError extends IpcConnectionError {\n readonly timeoutMs: number;\n\n constructor(timeoutMs: number, options: Pick<IpcConnectionErrorOptions, \"cause\"> = {}) {\n super(`AdofaiIpc request timed out after ${timeoutMs} ms.`, {\n code: \"TIMEOUT\",\n cause: options.cause\n });\n this.name = \"IpcTimeoutError\";\n this.timeoutMs = timeoutMs;\n }\n}\n\nexport class IpcVersionMismatchError extends AdofaiIpcError {\n readonly code = \"VERSION_MISMATCH\" as const;\n readonly clientVersion: string;\n readonly serverVersion: string | null;\n readonly direction: IpcVersionMismatchDirection;\n readonly protocolVersion: number | null;\n\n constructor(options: {\n clientVersion: string;\n serverVersion: string | null;\n direction: IpcVersionMismatchDirection;\n protocolVersion: number | null;\n }) {\n const server = options.serverVersion ?? \"legacy/unknown\";\n super(`AdofaiIpc version mismatch: client ${options.clientVersion}, server ${server}.`);\n this.name = \"IpcVersionMismatchError\";\n this.clientVersion = options.clientVersion;\n this.serverVersion = options.serverVersion;\n this.direction = options.direction;\n this.protocolVersion = options.protocolVersion;\n }\n}\n\nexport function isIpcUnavailable(error: unknown): error is IpcConnectionError {\n return error instanceof IpcConnectionError && error.code === \"UNAVAILABLE\";\n}\n\nexport class IpcHttpError extends AdofaiIpcError {\n readonly status: number;\n\n constructor(status: number, message: string) {\n super(message);\n this.name = \"IpcHttpError\";\n this.status = status;\n }\n}\n\nexport class IpcResponseError extends AdofaiIpcError {\n readonly code: string;\n readonly error: IpcErrorInfo;\n\n constructor(error: IpcErrorInfo) {\n super(error.message);\n this.name = \"IpcResponseError\";\n this.code = error.code;\n this.error = error;\n }\n}\n","declare const __CLIENT_VERSION__: string;\n\nexport const CLIENT_VERSION = __CLIENT_VERSION__;\n\nconst CANONICAL_SEMVER = /^(0|[1-9]\\d*)\\.(0|[1-9]\\d*)\\.(0|[1-9]\\d*)(?:-((?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*)(?:\\.(?:0|[1-9]\\d*|\\d*[A-Za-z-][0-9A-Za-z-]*))*))?$/;\n\ninterface ParsedVersion {\n core: [number, number, number];\n prerelease: string[] | null;\n}\n\nexport function compareProductVersions(left: string, right: string): number | null {\n const leftVersion = parseProductVersion(left);\n const rightVersion = parseProductVersion(right);\n if (!leftVersion || !rightVersion) return null;\n\n for (let index = 0; index < leftVersion.core.length; index++) {\n const difference = leftVersion.core[index]! - rightVersion.core[index]!;\n if (difference !== 0) return difference < 0 ? -1 : 1;\n }\n\n if (leftVersion.prerelease === null) return rightVersion.prerelease === null ? 0 : 1;\n if (rightVersion.prerelease === null) return -1;\n\n const length = Math.max(leftVersion.prerelease.length, rightVersion.prerelease.length);\n for (let index = 0; index < length; index++) {\n const leftPart = leftVersion.prerelease[index];\n const rightPart = rightVersion.prerelease[index];\n if (leftPart === undefined) return -1;\n if (rightPart === undefined) return 1;\n if (leftPart === rightPart) continue;\n\n const leftNumeric = /^\\d+$/.test(leftPart);\n const rightNumeric = /^\\d+$/.test(rightPart);\n if (leftNumeric && rightNumeric) return Number(leftPart) < Number(rightPart) ? -1 : 1;\n if (leftNumeric !== rightNumeric) return leftNumeric ? -1 : 1;\n return leftPart < rightPart ? -1 : 1;\n }\n\n return 0;\n}\n\nfunction parseProductVersion(value: string): ParsedVersion | null {\n const match = CANONICAL_SEMVER.exec(value);\n if (!match) return null;\n return {\n core: [Number(match[1]), Number(match[2]), Number(match[3])],\n prerelease: match[4] ? match[4].split(\".\") : null\n };\n}\n","import {\n IpcConnectionError,\n IpcHttpError,\n IpcResponseError,\n IpcTimeoutError,\n IpcVersionMismatchError\n} from \"./errors\";\nimport { CLIENT_VERSION, compareProductVersions } from \"./version\";\nimport type {\n AdofaiIpcClientOptions,\n IpcCallOptions,\n IpcErrorInfo,\n IpcHealthResponse,\n IpcNamespaceDetail,\n IpcNamespacesResponse,\n IpcRequestId,\n IpcRequestOptions,\n IpcResponse,\n TryConnectOptions,\n WaitForNamespaceOptions\n} from \"./types\";\n\nconst DEFAULT_HOST = \"127.0.0.1\";\nconst DEFAULT_START_PORT = 32145;\nconst DEFAULT_END_PORT = 32155;\nconst DEFAULT_PROBE_TIMEOUT_MS = 500;\nconst DEFAULT_REQUEST_TIMEOUT_MS = 10_000;\nconst DEFAULT_NAMESPACE_WAIT_TIMEOUT_MS = 10_000;\nconst DEFAULT_NAMESPACE_POLL_INTERVAL_MS = 100;\n\nexport class AdofaiIpcClient {\n readonly baseUrl: string;\n\n private readonly fetchImpl: typeof fetch;\n private readonly requestTimeoutMs: number;\n\n constructor(options: AdofaiIpcClientOptions = {}) {\n this.baseUrl = normalizeBaseUrl(options.baseUrl ?? `http://${DEFAULT_HOST}:${DEFAULT_START_PORT}`);\n this.fetchImpl = options.fetch ?? globalThis.fetch;\n this.requestTimeoutMs =\n options.requestTimeoutMs ?? options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n\n if (!this.fetchImpl) {\n throw new IpcConnectionError(\"A fetch implementation is required.\");\n }\n }\n\n static async connect(options: TryConnectOptions = {}): Promise<AdofaiIpcClient> {\n return tryConnect(options);\n }\n\n async health(options: IpcRequestOptions = {}): Promise<IpcHealthResponse> {\n return this.get<IpcHealthResponse>(\"/ipc/health\", options);\n }\n\n async listNamespaces(options: IpcRequestOptions = {}): Promise<IpcNamespacesResponse> {\n return this.get<IpcNamespacesResponse>(\"/ipc/namespaces\", options);\n }\n\n async getNamespace(\n namespace: string,\n options: IpcRequestOptions = {}\n ): Promise<IpcNamespaceDetail> {\n return this.get<IpcNamespaceDetail>(\n `/ipc/namespaces/${encodeURIComponent(namespace)}`,\n options\n );\n }\n\n async waitForNamespace(\n namespace: string,\n options: WaitForNamespaceOptions = {}\n ): Promise<IpcNamespaceDetail> {\n const timeoutMs = options.timeoutMs ?? DEFAULT_NAMESPACE_WAIT_TIMEOUT_MS;\n const pollIntervalMs = options.pollIntervalMs ?? DEFAULT_NAMESPACE_POLL_INTERVAL_MS;\n const requiredStatus = options.status ?? \"registered\";\n const deadline = Date.now() + timeoutMs;\n let stateError: IpcResponseError | undefined;\n\n while (true) {\n try {\n const detail = await this.getNamespace(namespace, {\n timeoutMs: options.requestTimeoutMs\n });\n\n if (requiredStatus === \"registered\" || detail.status === \"ready\") {\n return detail;\n }\n\n if (detail.status === \"error\") {\n throw new IpcResponseError({\n code: \"namespace_error\",\n message: detail.error?.message ?? `Namespace initialization failed: ${namespace}`\n });\n }\n\n if (detail.status !== \"initializing\") {\n throw new IpcResponseError({\n code: \"namespace_status_unavailable\",\n message: `Namespace status is unavailable: ${namespace}`\n });\n }\n\n stateError = new IpcResponseError({\n code: \"namespace_initializing\",\n message: `Namespace is initializing: ${namespace}`\n });\n } catch (error) {\n if (\n !(error instanceof IpcResponseError) ||\n (error.code !== \"namespace_not_found\" && error.code !== \"namespace_initializing\")\n ) {\n throw error;\n }\n\n stateError = error;\n }\n\n const remainingMs = deadline - Date.now();\n if (remainingMs <= 0) {\n throw stateError ?? new IpcResponseError({\n code: \"namespace_initializing\",\n message: `Namespace is initializing: ${namespace}`\n });\n }\n\n await delay(Math.min(pollIntervalMs, remainingMs));\n }\n }\n\n namespace(namespace: string): AdofaiIpcNamespaceClient {\n return new AdofaiIpcNamespaceClient(this, namespace);\n }\n\n async call<TResult = unknown, TParams = unknown>(\n options: IpcCallOptions<TParams>\n ): Promise<TResult> {\n const response = await this.post<IpcResponse<TResult>>(\n \"/ipc\",\n {\n namespace: options.namespace,\n method: options.method,\n params: options.params ?? {},\n id: options.id ?? createRequestId()\n },\n { timeoutMs: options.timeoutMs }\n );\n\n if (!response.ok) {\n throw new IpcResponseError(response.error);\n }\n\n return response.result;\n }\n\n private async get<TResult>(\n path: string,\n options: IpcRequestOptions = {}\n ): Promise<TResult> {\n return this.request<TResult>(path, {\n method: \"GET\"\n }, options);\n }\n\n private async post<TResult>(\n path: string,\n body: unknown,\n options: IpcRequestOptions = {}\n ): Promise<TResult> {\n return this.request<TResult>(path, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\"\n },\n body: JSON.stringify(body)\n }, options);\n }\n\n private async request<TResult>(\n path: string,\n init: RequestInit,\n options: IpcRequestOptions\n ): Promise<TResult> {\n const timeoutMs = options.timeoutMs ?? this.requestTimeoutMs;\n const controller = new AbortController();\n const timeoutError = new IpcTimeoutError(timeoutMs);\n const timeout = setTimeout(() => controller.abort(timeoutError), timeoutMs);\n\n try {\n const response = await this.fetchImpl(`${this.baseUrl}${path}`, {\n ...init,\n signal: controller.signal\n });\n\n if (!response.ok) {\n const text = await response.text();\n const responseError = parseIpcResponseError(text);\n if (responseError) throw new IpcResponseError(responseError);\n throw new IpcHttpError(response.status, text || response.statusText);\n }\n\n return (await response.json()) as TResult;\n } catch (error) {\n if (error instanceof IpcHttpError || error instanceof IpcResponseError) throw error;\n if (controller.signal.aborted) {\n if (error === timeoutError) throw timeoutError;\n throw new IpcTimeoutError(timeoutMs, { cause: error });\n }\n throw new IpcConnectionError(getErrorMessage(error), { cause: error });\n } finally {\n clearTimeout(timeout);\n }\n }\n}\n\nexport class AdofaiIpcNamespaceClient {\n constructor(\n private readonly client: AdofaiIpcClient,\n readonly namespace: string\n ) {\n }\n\n async call<TResult = unknown, TParams = unknown>(\n method: string,\n params?: TParams,\n idOrOptions?: IpcRequestId | IpcRequestOptions,\n options: IpcRequestOptions = {}\n ): Promise<TResult> {\n const requestOptions = isIpcRequestOptions(idOrOptions) ? idOrOptions : options;\n const id = isIpcRequestOptions(idOrOptions) ? undefined : idOrOptions;\n\n return this.client.call<TResult, TParams>({\n namespace: this.namespace,\n method,\n params,\n id,\n timeoutMs: requestOptions.timeoutMs\n });\n }\n}\n\nexport async function tryConnect(options: TryConnectOptions = {}): Promise<AdofaiIpcClient> {\n const host = options.host ?? DEFAULT_HOST;\n const startPort = options.startPort ?? DEFAULT_START_PORT;\n const endPort = options.endPort ?? DEFAULT_END_PORT;\n const probeTimeoutMs =\n options.probeTimeoutMs ?? options.timeoutMs ?? DEFAULT_PROBE_TIMEOUT_MS;\n const requestTimeoutMs =\n options.requestTimeoutMs ?? options.timeoutMs ?? DEFAULT_REQUEST_TIMEOUT_MS;\n let lastProbeError: unknown;\n\n for (let port = startPort; port <= endPort; port++) {\n const client = new AdofaiIpcClient({\n baseUrl: `http://${host}:${port}`,\n fetch: options.fetch,\n requestTimeoutMs: probeTimeoutMs\n });\n\n try {\n const health = await client.health();\n\n if (health.ok && health.server === \"AdofaiIpc\") {\n const mismatch = getVersionMismatch(health);\n if (mismatch) {\n try {\n options.onVersionMismatch?.(mismatch);\n } catch {\n }\n throw mismatch;\n }\n return new AdofaiIpcClient({\n baseUrl: client.baseUrl,\n fetch: options.fetch,\n requestTimeoutMs\n });\n }\n } catch (error) {\n if (error instanceof IpcVersionMismatchError) throw error;\n lastProbeError = error;\n }\n }\n\n if (lastProbeError instanceof IpcTimeoutError) throw lastProbeError;\n\n throw new IpcConnectionError(\n `Could not connect to AdofaiIpc on ${host}:${startPort}-${endPort}.`\n );\n}\n\nfunction getVersionMismatch(health: IpcHealthResponse): IpcVersionMismatchError | null {\n const protocolVersion = Number.isInteger(health.protocolVersion) ? health.protocolVersion : null;\n const serverVersion = typeof health.serverVersion === \"string\" ? health.serverVersion : null;\n const comparison = serverVersion === null\n ? null\n : compareProductVersions(serverVersion, CLIENT_VERSION);\n\n if (comparison === 0 && serverVersion === CLIENT_VERSION) return null;\n\n return new IpcVersionMismatchError({\n clientVersion: CLIENT_VERSION,\n serverVersion,\n direction: comparison === null\n ? \"legacy_server\"\n : comparison < 0\n ? \"server_outdated\"\n : \"client_outdated\",\n protocolVersion\n });\n}\n\nfunction normalizeBaseUrl(value: string): string {\n return value.replace(/\\/+$/, \"\");\n}\n\nfunction getErrorMessage(error: unknown): string | undefined {\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n return error.message;\n }\n\n return undefined;\n}\n\nfunction parseIpcResponseError(text: string): IpcErrorInfo | undefined {\n try {\n const value = JSON.parse(text) as { error?: unknown };\n const error = value?.error;\n\n if (\n typeof error === \"object\" &&\n error !== null &&\n \"code\" in error &&\n typeof error.code === \"string\" &&\n \"message\" in error &&\n typeof error.message === \"string\"\n ) {\n return { code: error.code, message: error.message };\n }\n } catch {\n }\n\n return undefined;\n}\n\nfunction isIpcRequestOptions(value: unknown): value is IpcRequestOptions {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction delay(timeoutMs: number): Promise<void> {\n return new Promise((resolve) => setTimeout(resolve, timeoutMs));\n}\n\nfunction createRequestId(): string {\n return `adofai-ipc-${Date.now()}-${Math.random().toString(36).slice(2)}`;\n}\n"],"mappings":"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","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adofai-ipc/client",
3
- "version": "0.2.0",
3
+ "version": "0.4.0",
4
4
  "description": "TypeScript client for the AdofaiIpc local HTTP IPC gateway.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -35,13 +35,6 @@
35
35
  "files": [
36
36
  "dist"
37
37
  ],
38
- "scripts": {
39
- "build": "tsup",
40
- "check": "tsc --noEmit",
41
- "clean": "rm -rf dist",
42
- "test": "pnpm run build && node --test test/*.test.mjs",
43
- "prepack": "pnpm run build"
44
- },
45
38
  "engines": {
46
39
  "node": ">=18"
47
40
  },
@@ -49,7 +42,14 @@
49
42
  "access": "public"
50
43
  },
51
44
  "devDependencies": {
45
+ "@types/node": "^22.10.2",
52
46
  "tsup": "^8.3.5",
53
47
  "typescript": "^5.6.3"
48
+ },
49
+ "scripts": {
50
+ "build": "tsup",
51
+ "check": "tsc --noEmit",
52
+ "clean": "rm -rf dist",
53
+ "test": "pnpm run build && node --test test/*.test.mjs"
54
54
  }
55
- }
55
+ }