@yydb/yydb-client 0.0.12 → 0.0.16

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/dist/client.d.ts CHANGED
@@ -3,7 +3,7 @@ import type { MicroHostHandler, Transport } from './transport.js';
3
3
  export type { Frame, MicroHostInvokePayload, MicroRegisterPayload, MsgTypeCode, SchemaVersion, WireErrorBody, WireUdfScalarKind, WireUdfScalarValue, } from './wire.js';
4
4
  export type { MicroHostHandler } from './transport.js';
5
5
  export { MsgType, encodeFrame, decodeFrame, encodeErrorBody, decodeErrorBody } from './wire.js';
6
- export { YydbError, YydbErrorCodes, isRetryableYydbCode, isYydbError } from './errors.js';
6
+ export { YydbError, YydbErrorCodes, YydbClientErrorCodes, isYydbError } from './errors.js';
7
7
  export type { YydbErrorCode, YydbErrorOptions } from './errors.js';
8
8
  export interface ConnectOptions {
9
9
  /** `ws://127.0.0.1:7700/wire` or `127.0.0.1:7700` (upgraded to `/wire`). */
package/dist/client.js CHANGED
@@ -2,7 +2,7 @@ import { decodeErrorBody, decodeKvGetOk, decodeScalarCallOk, decodeSchemaGetOk,
2
2
  import { openWebSocketTransport } from './ws.js';
3
3
  import { YydbError, YydbErrorCodes } from './errors.js';
4
4
  export { MsgType, encodeFrame, decodeFrame, encodeErrorBody, decodeErrorBody } from './wire.js';
5
- export { YydbError, YydbErrorCodes, isRetryableYydbCode, isYydbError } from './errors.js';
5
+ export { YydbError, YydbErrorCodes, YydbClientErrorCodes, isYydbError } from './errors.js';
6
6
  /** Expected reply type and operation label per request type. */
7
7
  const REQUESTS = {
8
8
  [MsgType.Hello]: { operation: 'hello', ok: MsgType.HelloOk },
@@ -47,6 +47,7 @@ export class Client {
47
47
  catch (cause) {
48
48
  throw new YydbError(YydbErrorCodes.clientTransportFailure, `connect ${endpoint}: transport failed`, {
49
49
  operation: 'connect',
50
+ retryable: true,
50
51
  cause,
51
52
  });
52
53
  }
@@ -122,7 +123,7 @@ export class Client {
122
123
  });
123
124
  }
124
125
  catch (cause) {
125
- throw new YydbError(YydbErrorCodes.clientTransportFailure, `${operation}: transport failed`, { operation, cause });
126
+ throw new YydbError(YydbErrorCodes.clientTransportFailure, `${operation}: transport failed`, { operation, retryable: true, cause });
126
127
  }
127
128
  if (response.requestId !== requestId) {
128
129
  throw new YydbError(YydbErrorCodes.clientRequestIdMismatch, `${operation}: wire response request_id mismatch (got ${response.requestId}, want ${requestId})`, { operation });
package/dist/errors.d.ts CHANGED
@@ -1,57 +1,87 @@
1
1
  /**
2
- * Host-facing YYDB error surface.
2
+ * @yydb/yydb-client 公共错误面。
3
3
  *
4
- * Every public failure carries a stable `code`: engine codes come from the
5
- * Rust core (`yydb.schema.invalid`, …) over the wire, client codes are minted
6
- * locally with the `yydb.client.` prefix. Branch on `code` — `message` is
7
- * display text only.
4
+ * 与 Node 嵌入式库 `@yydb/yydb` 共享同一错误合同:稳定 `code` 字符串、
5
+ * `operation`、`retryable`、`params`。**分支依据是 `code` 不是 `message`。**
6
+ *
7
+ * 引擎侧错误 code 字符串来自 Rust 内核(经 wire 协议传入),这里不维护
8
+ * 引擎 code 常量表——Rust 新增变体时 host 直接拿到字符串即可。
9
+ *
10
+ * Client 本地错误(`yydb.client.*`)只在本包 mint,不流入 Rust。
11
+ *
12
+ * 本包与 `@yydb/yydb` **互不依赖**——错误合同在各自边界独立持有。
8
13
  */
9
- /** Stable codes known to the TypeScript hosts. */
10
- export declare const YydbErrorCodes: {
11
- readonly io: "yydb.io";
12
- readonly corrupt: "yydb.corrupt";
13
- readonly schemaConflict: "yydb.schema.conflict";
14
- readonly schemaInvalid: "yydb.schema.invalid";
15
- readonly udfNotFound: "yydb.udf.not_found";
16
- readonly udfArity: "yydb.udf.arity";
17
- readonly udfFailed: "yydb.udf.failed";
18
- readonly udfVersionMismatch: "yydb.udf.version_mismatch";
19
- readonly objectNotFound: "yydb.object.not_found";
20
- readonly objectCorrupt: "yydb.object.corrupt";
21
- readonly unsupported: "yydb.unsupported";
22
- readonly protocol: "yydb.protocol";
23
- readonly casConflict: "yydb.cas.conflict";
24
- readonly leaseUnavailable: "yydb.lease.unavailable";
25
- readonly fencingMismatch: "yydb.fencing.mismatch";
26
- readonly leaseExpired: "yydb.lease.expired";
27
- readonly quotaExceeded: "yydb.quota.exceeded";
14
+ /**
15
+ * Client 侧专属错误 code(永远不来自 Rust)。
16
+ */
17
+ export declare const YydbClientErrorCodes: {
18
+ /** serve() endpoint 为空或无效。 */
19
+ readonly clientInvalidEndpoint: "yydb.client.invalid_endpoint";
20
+ /** connect() socket / transport 层失败。 */
21
+ readonly clientTransportFailure: "yydb.client.transport_failure";
22
+ /** Server 返回的 request id 与请求不匹配。 */
23
+ readonly clientRequestIdMismatch: "yydb.client.request_id_mismatch";
24
+ /** Server 返回了未请求的 msg_type。 */
25
+ readonly clientUnexpectedResponse: "yydb.client.unexpected_response";
26
+ /** 无法解析 wire Error frame body。 */
27
+ readonly clientDecodeFailure: "yydb.client.decode_failure";
28
+ /** YYDB session 已关闭。 */
28
29
  readonly sessionClosed: "yydb.session.closed";
30
+ };
31
+ /**
32
+ * 所有已知 client error code 的联合(引擎 code 作为字符串直接使用)。
33
+ */
34
+ export declare const YydbErrorCodes: {
35
+ /** serve() endpoint 为空或无效。 */
29
36
  readonly clientInvalidEndpoint: "yydb.client.invalid_endpoint";
37
+ /** connect() socket / transport 层失败。 */
30
38
  readonly clientTransportFailure: "yydb.client.transport_failure";
39
+ /** Server 返回的 request id 与请求不匹配。 */
31
40
  readonly clientRequestIdMismatch: "yydb.client.request_id_mismatch";
41
+ /** Server 返回了未请求的 msg_type。 */
32
42
  readonly clientUnexpectedResponse: "yydb.client.unexpected_response";
43
+ /** 无法解析 wire Error frame body。 */
33
44
  readonly clientDecodeFailure: "yydb.client.decode_failure";
45
+ /** YYDB session 已关闭。 */
46
+ readonly sessionClosed: "yydb.session.closed";
34
47
  };
35
- /** A known code, or any future code the engine introduces. */
36
- export type YydbErrorCode = (typeof YydbErrorCodes)[keyof typeof YydbErrorCodes] | (string & {});
37
- /** Whether `code` may be retried with the same arguments. */
38
- export declare function isRetryableYydbCode(code: string): boolean;
39
- /** Options carried by a {@link YydbError}. */
48
+ /** 稳定错误 code 字符串。引擎 code 来自 Rust,client code 来自本包常量。 */
49
+ export type YydbErrorCode = string;
50
+ /** {@link YydbError} 构造参数。 */
40
51
  export interface YydbErrorOptions {
41
- /** Operation that failed (`schemaGet`, `kvPut`, `query`, …). */
52
+ /** 失败操作(`schemaGet`、`kvPut`、`query` …)。 */
42
53
  operation?: string;
43
- /** Underlying failure when this error wraps one. */
54
+ /**
55
+ * 相同参数是否可重试。
56
+ *
57
+ * 缺省为 `false`(保守)。client 侧 mint 的可重试错误(如
58
+ * `yydb.client.transport_failure`)**必须**显式设置。引擎侧经 wire 传入
59
+ * 的错误携带 Rust 权威 retryable 值,解析时覆盖默认。
60
+ */
61
+ retryable?: boolean;
62
+ /** 结构化参数,供 catalog 模板化渲染使用。 */
63
+ params?: Readonly<Record<string, string>>;
64
+ /** 被本错误包装的底层失败。 */
44
65
  cause?: unknown;
45
66
  }
46
- /** YYDB failure with a stable machine-readable {@link YydbError.code}. */
67
+ /** 带稳定机器可读 `code` 的 YYDB 错误。 */
47
68
  export declare class YydbError extends Error {
48
- /** Stable code — engine code or `yydb.client.*`. */
69
+ /** 稳定 code —— 引擎侧来自 Rust,或 `yydb.client.*`。 */
49
70
  readonly code: string;
50
- /** Operation that failed. */
71
+ /** 失败操作。 */
51
72
  readonly operation: string;
52
- /** Whether the same call may be retried. */
73
+ /** 是否可重试。 */
53
74
  readonly retryable: boolean;
75
+ /** 结构化参数(存在时)。 */
76
+ readonly params?: Readonly<Record<string, string>>;
54
77
  constructor(code: YydbErrorCode, message: string, options?: YydbErrorOptions);
78
+ /**
79
+ * 从 wire error body(JSON)解析出 {@link YydbError}。格式:
80
+ * `{ code, operation?, retryable?, message, params? }`。
81
+ *
82
+ * 返回解析后的 {@link YydbError};纯文本输入返回 `null`。
83
+ */
84
+ static fromDiagnosticJson(value: unknown): YydbError | null;
55
85
  }
56
- /** Narrowing helper so callers can branch without `instanceof` imports. */
86
+ /** 让调用方无需 `instanceof` import 即可收窄。 */
57
87
  export declare function isYydbError(value: unknown): value is YydbError;
package/dist/errors.js CHANGED
@@ -1,68 +1,109 @@
1
1
  /**
2
- * Host-facing YYDB error surface.
2
+ * @yydb/yydb-client 公共错误面。
3
3
  *
4
- * Every public failure carries a stable `code`: engine codes come from the
5
- * Rust core (`yydb.schema.invalid`, …) over the wire, client codes are minted
6
- * locally with the `yydb.client.` prefix. Branch on `code` — `message` is
7
- * display text only.
4
+ * 与 Node 嵌入式库 `@yydb/yydb` 共享同一错误合同:稳定 `code` 字符串、
5
+ * `operation`、`retryable`、`params`。**分支依据是 `code` 不是 `message`。**
6
+ *
7
+ * 引擎侧错误 code 字符串来自 Rust 内核(经 wire 协议传入),这里不维护
8
+ * 引擎 code 常量表——Rust 新增变体时 host 直接拿到字符串即可。
9
+ *
10
+ * Client 本地错误(`yydb.client.*`)只在本包 mint,不流入 Rust。
11
+ *
12
+ * 本包与 `@yydb/yydb` **互不依赖**——错误合同在各自边界独立持有。
8
13
  */
9
- /** Stable codes known to the TypeScript hosts. */
10
- export const YydbErrorCodes = {
11
- io: 'yydb.io',
12
- corrupt: 'yydb.corrupt',
13
- schemaConflict: 'yydb.schema.conflict',
14
- schemaInvalid: 'yydb.schema.invalid',
15
- udfNotFound: 'yydb.udf.not_found',
16
- udfArity: 'yydb.udf.arity',
17
- udfFailed: 'yydb.udf.failed',
18
- udfVersionMismatch: 'yydb.udf.version_mismatch',
19
- objectNotFound: 'yydb.object.not_found',
20
- objectCorrupt: 'yydb.object.corrupt',
21
- unsupported: 'yydb.unsupported',
22
- protocol: 'yydb.protocol',
23
- casConflict: 'yydb.cas.conflict',
24
- leaseUnavailable: 'yydb.lease.unavailable',
25
- fencingMismatch: 'yydb.fencing.mismatch',
26
- leaseExpired: 'yydb.lease.expired',
27
- quotaExceeded: 'yydb.quota.exceeded',
28
- sessionClosed: 'yydb.session.closed',
14
+ /**
15
+ * Client 侧专属错误 code(永远不来自 Rust)。
16
+ */
17
+ export const YydbClientErrorCodes = {
18
+ /** serve() endpoint 为空或无效。 */
29
19
  clientInvalidEndpoint: 'yydb.client.invalid_endpoint',
20
+ /** connect() socket / transport 层失败。 */
30
21
  clientTransportFailure: 'yydb.client.transport_failure',
22
+ /** Server 返回的 request id 与请求不匹配。 */
31
23
  clientRequestIdMismatch: 'yydb.client.request_id_mismatch',
24
+ /** Server 返回了未请求的 msg_type。 */
32
25
  clientUnexpectedResponse: 'yydb.client.unexpected_response',
26
+ /** 无法解析 wire Error frame body。 */
33
27
  clientDecodeFailure: 'yydb.client.decode_failure',
28
+ /** YYDB session 已关闭。 */
29
+ sessionClosed: 'yydb.session.closed',
34
30
  };
35
31
  /**
36
- * Codes where retrying the same operation can legitimately succeed: a socket or
37
- * lease hiccup, or a compare-and-set that lost a benign race. Every other code
38
- * needs the caller to change input, schema, or wiring first.
32
+ * 所有已知 client error code 的联合(引擎 code 作为字符串直接使用)。
39
33
  */
40
- const RETRYABLE_CODES = new Set([
41
- YydbErrorCodes.clientTransportFailure,
42
- YydbErrorCodes.casConflict,
43
- YydbErrorCodes.leaseUnavailable,
44
- ]);
45
- /** Whether `code` may be retried with the same arguments. */
46
- export function isRetryableYydbCode(code) {
47
- return RETRYABLE_CODES.has(code);
48
- }
49
- /** YYDB failure with a stable machine-readable {@link YydbError.code}. */
34
+ export const YydbErrorCodes = {
35
+ ...YydbClientErrorCodes,
36
+ };
37
+ /** 带稳定机器可读 `code` 的 YYDB 错误。 */
50
38
  export class YydbError extends Error {
51
- /** Stable code — engine code or `yydb.client.*`. */
39
+ /** 稳定 code —— 引擎侧来自 Rust,或 `yydb.client.*`。 */
52
40
  code;
53
- /** Operation that failed. */
41
+ /** 失败操作。 */
54
42
  operation;
55
- /** Whether the same call may be retried. */
43
+ /** 是否可重试。 */
56
44
  retryable;
45
+ /** 结构化参数(存在时)。 */
46
+ params;
57
47
  constructor(code, message, options = {}) {
58
48
  super(message, { cause: options.cause });
59
49
  this.name = 'YydbError';
60
50
  this.code = code;
61
51
  this.operation = options.operation ?? 'unknown';
62
- this.retryable = isRetryableYydbCode(code);
52
+ this.retryable = options.retryable ?? false;
53
+ if (options.params !== undefined) {
54
+ this.params = options.params;
55
+ }
56
+ }
57
+ /**
58
+ * 从 wire error body(JSON)解析出 {@link YydbError}。格式:
59
+ * `{ code, operation?, retryable?, message, params? }`。
60
+ *
61
+ * 返回解析后的 {@link YydbError};纯文本输入返回 `null`。
62
+ */
63
+ static fromDiagnosticJson(value) {
64
+ let obj;
65
+ if (typeof value === 'string') {
66
+ try {
67
+ const parsed = JSON.parse(value);
68
+ if (!parsed || typeof parsed !== 'object')
69
+ return null;
70
+ obj = parsed;
71
+ }
72
+ catch {
73
+ return null;
74
+ }
75
+ }
76
+ else if (value && typeof value === 'object') {
77
+ obj = value;
78
+ }
79
+ else {
80
+ return null;
81
+ }
82
+ // WASM envelopes nest the diagnostic under `{ ok, error: {...} }`.
83
+ let diag = obj;
84
+ if (typeof obj['ok'] === 'boolean' && !obj['ok'] && obj['error'] && typeof obj['error'] === 'object') {
85
+ diag = obj['error'];
86
+ }
87
+ const code = typeof diag['code'] === 'string' ? diag['code'] : null;
88
+ const message = typeof diag['message'] === 'string' ? diag['message'] : '';
89
+ if (!code)
90
+ return null;
91
+ const operation = typeof diag['operation'] === 'string' ? diag['operation'] : undefined;
92
+ const retryable = typeof diag['retryable'] === 'boolean' ? diag['retryable'] : undefined;
93
+ const params = diag['params'] && typeof diag['params'] === 'object'
94
+ ? diag['params']
95
+ : undefined;
96
+ const opts = {};
97
+ if (operation !== undefined)
98
+ opts.operation = operation;
99
+ if (retryable !== undefined)
100
+ opts.retryable = retryable;
101
+ if (params !== undefined)
102
+ opts.params = params;
103
+ return new YydbError(code, message, opts);
63
104
  }
64
105
  }
65
- /** Narrowing helper so callers can branch without `instanceof` imports. */
106
+ /** 让调用方无需 `instanceof` import 即可收窄。 */
66
107
  export function isYydbError(value) {
67
108
  return value instanceof YydbError;
68
109
  }
package/dist/index.d.ts CHANGED
@@ -3,6 +3,6 @@ export { Client } from './client.js';
3
3
  export type { ConnectOptions } from './client.js';
4
4
  export { MAGIC, MAGIC_YYDB, MAGIC_YYDS, WIRE_VERSION, WIRE_VERSION_NEXT, HEADER_LEN, MsgType, encodeFrame, decodeFrame, encodeSchemaEnsure, encodeKvGet, encodeKvPut, encodeMicroRegister, encodeScalarCall, encodeErrorBody, decodeErrorBody, decodeScalarCallOk, decodeSchemaGetOk, decodeKvGetOk, } from './wire.js';
5
5
  export type { Frame, MicroRegisterPayload, MsgTypeCode, ProductMagic, SchemaVersion, WireErrorBody, WireUdfScalarKind, WireUdfScalarValue, } from './wire.js';
6
- export { YydbError, YydbErrorCodes, isRetryableYydbCode, isYydbError } from './errors.js';
6
+ export { YydbError, YydbErrorCodes, YydbClientErrorCodes, isYydbError } from './errors.js';
7
7
  export type { YydbErrorCode, YydbErrorOptions } from './errors.js';
8
8
  export type { MicroHostHandler, Transport } from './transport.js';
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
1
  /** Browser-safe entry (WebSocket). For Node TCP use `@yydb/yydb-client/node`. */
2
2
  export { Client } from './client.js';
3
3
  export { MAGIC, MAGIC_YYDB, MAGIC_YYDS, WIRE_VERSION, WIRE_VERSION_NEXT, HEADER_LEN, MsgType, encodeFrame, decodeFrame, encodeSchemaEnsure, encodeKvGet, encodeKvPut, encodeMicroRegister, encodeScalarCall, encodeErrorBody, decodeErrorBody, decodeScalarCallOk, decodeSchemaGetOk, decodeKvGetOk, } from './wire.js';
4
- export { YydbError, YydbErrorCodes, isRetryableYydbCode, isYydbError } from './errors.js';
4
+ export { YydbError, YydbErrorCodes, YydbClientErrorCodes, isYydbError } from './errors.js';
package/dist/node.d.ts CHANGED
@@ -3,7 +3,7 @@ export { Client } from './client.js';
3
3
  export type { ConnectOptions } from './client.js';
4
4
  export { MsgType, encodeFrame, decodeFrame, encodeSchemaEnsure, encodeKvGet, encodeKvPut, decodeSchemaGetOk, decodeKvGetOk, encodeErrorBody, decodeErrorBody, } from './wire.js';
5
5
  export type { Frame, MsgTypeCode, SchemaVersion, WireErrorBody } from './wire.js';
6
- export { YydbError, YydbErrorCodes, isRetryableYydbCode, isYydbError } from './errors.js';
6
+ export { YydbError, YydbErrorCodes, YydbClientErrorCodes, isYydbError } from './errors.js';
7
7
  export type { YydbErrorCode, YydbErrorOptions } from './errors.js';
8
8
  export type { MicroHostHandler, Transport } from './transport.js';
9
9
  /** Node entry: TCP by default; `ws://` uses WebSocket. */
package/dist/node.js CHANGED
@@ -5,7 +5,7 @@ import { normalizeWsUrl } from './transport.js';
5
5
  import { YydbError, YydbErrorCodes } from './errors.js';
6
6
  export { Client } from './client.js';
7
7
  export { MsgType, encodeFrame, decodeFrame, encodeSchemaEnsure, encodeKvGet, encodeKvPut, decodeSchemaGetOk, decodeKvGetOk, encodeErrorBody, decodeErrorBody, } from './wire.js';
8
- export { YydbError, YydbErrorCodes, isRetryableYydbCode, isYydbError } from './errors.js';
8
+ export { YydbError, YydbErrorCodes, YydbClientErrorCodes, isYydbError } from './errors.js';
9
9
  function wantsWebSocket(endpoint) {
10
10
  const trimmed = endpoint.trim();
11
11
  return trimmed.startsWith('ws://') || trimmed.startsWith('wss://');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yydb/yydb-client",
3
- "version": "0.0.12",
3
+ "version": "0.0.16",
4
4
  "description": "TypeScript client for the YYDB WebSocket and TCP wire protocol",
5
5
  "license": "MPL-2.0",
6
6
  "type": "module",