@nominalso/vibe-host 0.5.0 → 0.5.1

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/index.cjs CHANGED
@@ -27,7 +27,7 @@ __export(index_exports, {
27
27
  module.exports = __toCommonJS(index_exports);
28
28
 
29
29
  // package.json
30
- var version = "0.5.0";
30
+ var version = "0.5.1";
31
31
 
32
32
  // ../protocol-types/dist/index.js
33
33
  function normalizeSubroute(subroute) {
@@ -58,20 +58,46 @@ function isBridgeMessage(data) {
58
58
  if (CORRELATED_KINDS_SET.has(d.kind) && typeof d.requestId !== "string") return false;
59
59
  return true;
60
60
  }
61
+ var BRIDGE_ERROR_BRAND = /* @__PURE__ */ Symbol.for("@nominalso/vibe-bridge:BridgeError");
62
+ var HTTP_BRIDGE_ERROR_BRAND = /* @__PURE__ */ Symbol.for("@nominalso/vibe-bridge:HttpBridgeError");
61
63
  var BridgeError = class extends Error {
62
64
  constructor(code, message) {
63
65
  super(message);
64
66
  this.code = code;
65
67
  this.name = "BridgeError";
66
68
  }
69
+ /**
70
+ * Cross-realm-safe type guard. Prefer this over `instanceof BridgeError` when
71
+ * an error may have been thrown by a differently-built copy of the SDK (e.g.
72
+ * server bundle vs client bundle) — it matches on a process-global brand
73
+ * rather than class identity.
74
+ */
75
+ static isBridgeError(err) {
76
+ return typeof err === "object" && err !== null && err[BRIDGE_ERROR_BRAND] === true;
77
+ }
67
78
  };
79
+ Object.defineProperty(BridgeError.prototype, BRIDGE_ERROR_BRAND, {
80
+ value: true,
81
+ enumerable: false
82
+ });
68
83
  var HttpBridgeError = class extends BridgeError {
69
84
  constructor(status, message) {
70
85
  super("REQUEST_FAILED", message);
71
86
  this.status = status;
72
87
  this.name = "HttpBridgeError";
73
88
  }
89
+ /**
90
+ * Cross-realm-safe type guard (see {@link BridgeError.isBridgeError}). Returns
91
+ * `true` only for `HttpBridgeError` instances, not plain `BridgeError`s.
92
+ */
93
+ static isHttpBridgeError(err) {
94
+ return typeof err === "object" && err !== null && err[HTTP_BRIDGE_ERROR_BRAND] === true;
95
+ }
74
96
  };
97
+ Object.defineProperty(HttpBridgeError.prototype, HTTP_BRIDGE_ERROR_BRAND, {
98
+ value: true,
99
+ enumerable: false
100
+ });
75
101
  function isOriginPattern(entry) {
76
102
  return entry.includes("*");
77
103
  }
package/dist/index.d.cts CHANGED
@@ -3265,6 +3265,28 @@ interface ContextPayload {
3265
3265
  hostVersion: string;
3266
3266
  }
3267
3267
 
3268
+ /**
3269
+ * Response type for operations whose Nominal OpenAPI `200` response declares
3270
+ * **no content schema**. hey-api generates `200: unknown` for these, so there is
3271
+ * genuinely no concrete type to narrow to at codegen time — the shape is
3272
+ * undocumented upstream, not merely unmapped by this SDK.
3273
+ *
3274
+ * We surface this named alias instead of a bare `unknown` so the gap is
3275
+ * self-documenting: editors show `UntypedApiResponse` (with this doc) rather than
3276
+ * an anonymous `unknown`, signalling that the value must be explicitly asserted
3277
+ * to a known shape (`const p = res as MyPeriod`) rather than trusted. It stays
3278
+ * assignment-compatible with `unknown`, so no runtime or narrowing behaviour
3279
+ * changes.
3280
+ *
3281
+ * The fix is upstream: document these endpoints' response bodies in the owning
3282
+ * Nominal service's OpenAPI (then the registry entry can reference the generated
3283
+ * `*Response` type). Affected ops today: `GET_PERIODS`, `GET_PERIOD_INSTANCE`,
3284
+ * `GET_PERIOD_INSTANCE_BY_SLUG`, `POST_TASK_OUTPUT`, `GET_TASK_INSTANCE`,
3285
+ * `GET_TASK_INSTANCES`, `GET_TASK_DEFINITION`, `GET_ACTIVITY_DEFINITION(S)`,
3286
+ * `GET_ACTIVITY_INSTANCE`, `GET_ACTIVITY_INSTANCE_TASKS`,
3287
+ * `GET_ACTIVITY_PERIOD_TASKS`.
3288
+ */
3289
+ type UntypedApiResponse = unknown;
3268
3290
  interface UploadPayload {
3269
3291
  buffer: ArrayBuffer;
3270
3292
  fileName: string;
@@ -3337,11 +3359,11 @@ interface RequestRegistry {
3337
3359
  };
3338
3360
  GET_PERIODS: {
3339
3361
  payload: Omit<GetPeriodInstancesApiActivityPeriodInstanceGetData, 'url'>;
3340
- data: unknown;
3362
+ data: UntypedApiResponse;
3341
3363
  };
3342
3364
  POST_TASK_OUTPUT: {
3343
3365
  payload: Omit<UpdateTaskInstanceApiActivityTaskInstanceTaskInstanceIdPutData, 'url'>;
3344
- data: unknown;
3366
+ data: UntypedApiResponse;
3345
3367
  };
3346
3368
  GET_DIMENSIONS: {
3347
3369
  payload: Omit<GetDimensionsApiAccountingDimensionGetData, 'url'>;
@@ -3357,7 +3379,7 @@ interface RequestRegistry {
3357
3379
  };
3358
3380
  GET_ACTIVITY_DEFINITIONS: {
3359
3381
  payload: Omit<GetActivityDefinitionsApiActivityActivityDefinitionGetData, 'url'>;
3360
- data: unknown;
3382
+ data: UntypedApiResponse;
3361
3383
  };
3362
3384
  GET_TASK_DEFINITIONS: {
3363
3385
  payload: Omit<GetAllTasksDefinitionsApiActivityTaskDefinitionGetData, 'url'>;
@@ -3365,7 +3387,7 @@ interface RequestRegistry {
3365
3387
  };
3366
3388
  GET_TASK_INSTANCES: {
3367
3389
  payload: Omit<GetAllTaskInstancesApiActivityTaskInstanceGetData, 'url'>;
3368
- data: unknown;
3390
+ data: UntypedApiResponse;
3369
3391
  };
3370
3392
  GET_FISCAL_CALENDARS: {
3371
3393
  payload: Omit<GetFiscalCalendarsBySubsidiaryApiPeriodManagerFiscalCalendarBySubsidiarySubsidiaryIdGetData, 'url'>;
@@ -3433,11 +3455,11 @@ interface RequestRegistry {
3433
3455
  };
3434
3456
  GET_PERIOD_INSTANCE: {
3435
3457
  payload: Omit<GetPeriodInstanceApiActivityPeriodInstancePeriodInstanceIdGetData, 'url'>;
3436
- data: unknown;
3458
+ data: UntypedApiResponse;
3437
3459
  };
3438
3460
  GET_PERIOD_INSTANCE_BY_SLUG: {
3439
3461
  payload: Omit<GetPeriodInstanceBySlugApiActivityPeriodInstanceBySlugPeriodDisplayIdGetData, 'url'>;
3440
- data: unknown;
3462
+ data: UntypedApiResponse;
3441
3463
  };
3442
3464
  GET_PERIOD_PROGRESS_BREAKDOWN: {
3443
3465
  payload: Omit<GetPeriodInstanceProgressBreakdownBySlugApiActivityPeriodInstanceBySlugPeriodDisplayIdProgressBreakdownGetData, 'url'>;
@@ -3445,7 +3467,7 @@ interface RequestRegistry {
3445
3467
  };
3446
3468
  GET_ACTIVITY_DEFINITION: {
3447
3469
  payload: Omit<GetActivityDefinitionByIdApiActivityActivityDefinitionActivityDefinitionIdGetData, 'url'>;
3448
- data: unknown;
3470
+ data: UntypedApiResponse;
3449
3471
  };
3450
3472
  GET_ACTIVITY_INSTANCES: {
3451
3473
  payload: Omit<GetActivityInstancesApiActivityActivityInstanceGetData, 'url'>;
@@ -3453,7 +3475,7 @@ interface RequestRegistry {
3453
3475
  };
3454
3476
  GET_ACTIVITY_INSTANCE: {
3455
3477
  payload: Omit<GetActivityInstanceApiActivityActivityInstanceActivityInstanceIdGetData, 'url'>;
3456
- data: unknown;
3478
+ data: UntypedApiResponse;
3457
3479
  };
3458
3480
  GET_ACTIVITY_INSTANCE_BY_PERIOD: {
3459
3481
  payload: Omit<GetActivityInstanceByPeriodApiActivityActivityInstanceByPeriodPeriodDisplayIdActivityDefinitionIdGetData, 'url'>;
@@ -3461,15 +3483,15 @@ interface RequestRegistry {
3461
3483
  };
3462
3484
  GET_ACTIVITY_INSTANCE_TASKS: {
3463
3485
  payload: Omit<GetTaskInstancesByActivityApiActivityActivityInstanceActivityInstanceIdTaskGetData, 'url'>;
3464
- data: unknown;
3486
+ data: UntypedApiResponse;
3465
3487
  };
3466
3488
  GET_ACTIVITY_PERIOD_TASKS: {
3467
3489
  payload: Omit<GetTaskInstancesByActivityPeriodApiActivityActivityInstanceByPeriodPeriodDisplayIdActivityDefinitionIdTaskGetData, 'url'>;
3468
- data: unknown;
3490
+ data: UntypedApiResponse;
3469
3491
  };
3470
3492
  GET_TASK_DEFINITION: {
3471
3493
  payload: Omit<GetTaskDefinitionByIdApiActivityTaskDefinitionTaskDefinitionIdGetData, 'url'>;
3472
- data: unknown;
3494
+ data: UntypedApiResponse;
3473
3495
  };
3474
3496
  CREATE_TASK_DEFINITION: {
3475
3497
  payload: Omit<CreateTaskDefinitionApiActivityTaskDefinitionPostData, 'url'>;
@@ -3485,7 +3507,7 @@ interface RequestRegistry {
3485
3507
  };
3486
3508
  GET_TASK_INSTANCE: {
3487
3509
  payload: Omit<GetTaskInstanceByIdApiActivityTaskInstanceTaskInstanceIdGetData, 'url'>;
3488
- data: unknown;
3510
+ data: UntypedApiResponse;
3489
3511
  };
3490
3512
  GET_TASK_INSTANCES_BY_FILTER: {
3491
3513
  payload: Omit<GetAllTaskInstancesByFilterApiActivityTaskInstanceQueryPostData, 'url'>;
@@ -3545,12 +3567,24 @@ type RequestHandlers = {
3545
3567
  * string-matching `error.message`. A failed Nominal API call rehydrates as the
3546
3568
  * {@link HttpBridgeError} subtype, which adds the HTTP `status`.
3547
3569
  *
3570
+ * SDK-originated codes you may also see: `'TIMEOUT'` (a request or the connect
3571
+ * handshake timed out), `'DESTROYED'` (the bridge was torn down mid-flight),
3572
+ * `'PARENT_ORIGIN_UNRESOLVED'` (no embedding origin could be resolved) and
3573
+ * `'SERVER_ENVIRONMENT'` (a browser-only method was called where there is no
3574
+ * `window` — e.g. during SSR / in a React Server Component / in a Worker).
3575
+ *
3576
+ * This class is safe to import from any environment (see the module header).
3577
+ *
3548
3578
  * @example
3549
3579
  * ```ts
3580
+ * import { BridgeError } from '@nominalso/vibe-bridge'
3581
+ *
3550
3582
  * try {
3551
3583
  * await bridge.getAccounts({})
3552
3584
  * } catch (err) {
3553
- * if (err instanceof BridgeError && err.code === 'RATE_LIMITED') {
3585
+ * // `instanceof` works within a single bundle; `isBridgeError` also works
3586
+ * // across independently-built server/client bundles.
3587
+ * if (BridgeError.isBridgeError(err) && err.code === 'RATE_LIMITED') {
3554
3588
  * // back off and retry
3555
3589
  * }
3556
3590
  * }
@@ -3559,6 +3593,13 @@ type RequestHandlers = {
3559
3593
  declare class BridgeError extends Error {
3560
3594
  readonly code: string;
3561
3595
  constructor(code: string, message: string);
3596
+ /**
3597
+ * Cross-realm-safe type guard. Prefer this over `instanceof BridgeError` when
3598
+ * an error may have been thrown by a differently-built copy of the SDK (e.g.
3599
+ * server bundle vs client bundle) — it matches on a process-global brand
3600
+ * rather than class identity.
3601
+ */
3602
+ static isBridgeError(err: unknown): err is BridgeError;
3562
3603
  }
3563
3604
  /**
3564
3605
  * A {@link BridgeError} for a failed Nominal API call. Its `code` is always
@@ -3568,10 +3609,12 @@ declare class BridgeError extends Error {
3568
3609
  *
3569
3610
  * @example
3570
3611
  * ```ts
3612
+ * import { HttpBridgeError } from '@nominalso/vibe-bridge'
3613
+ *
3571
3614
  * try {
3572
3615
  * await bridge.getAccount({ path: { account_id: 'missing' } })
3573
3616
  * } catch (err) {
3574
- * if (err instanceof HttpBridgeError && err.status === 404) {
3617
+ * if (HttpBridgeError.isHttpBridgeError(err) && err.status === 404) {
3575
3618
  * // handle not-found
3576
3619
  * }
3577
3620
  * }
@@ -3580,6 +3623,11 @@ declare class BridgeError extends Error {
3580
3623
  declare class HttpBridgeError extends BridgeError {
3581
3624
  readonly status: number;
3582
3625
  constructor(status: number, message: string);
3626
+ /**
3627
+ * Cross-realm-safe type guard (see {@link BridgeError.isBridgeError}). Returns
3628
+ * `true` only for `HttpBridgeError` instances, not plain `BridgeError`s.
3629
+ */
3630
+ static isHttpBridgeError(err: unknown): err is HttpBridgeError;
3583
3631
  }
3584
3632
 
3585
3633
  interface VibeApiClientOptions {
package/dist/index.d.ts CHANGED
@@ -3265,6 +3265,28 @@ interface ContextPayload {
3265
3265
  hostVersion: string;
3266
3266
  }
3267
3267
 
3268
+ /**
3269
+ * Response type for operations whose Nominal OpenAPI `200` response declares
3270
+ * **no content schema**. hey-api generates `200: unknown` for these, so there is
3271
+ * genuinely no concrete type to narrow to at codegen time — the shape is
3272
+ * undocumented upstream, not merely unmapped by this SDK.
3273
+ *
3274
+ * We surface this named alias instead of a bare `unknown` so the gap is
3275
+ * self-documenting: editors show `UntypedApiResponse` (with this doc) rather than
3276
+ * an anonymous `unknown`, signalling that the value must be explicitly asserted
3277
+ * to a known shape (`const p = res as MyPeriod`) rather than trusted. It stays
3278
+ * assignment-compatible with `unknown`, so no runtime or narrowing behaviour
3279
+ * changes.
3280
+ *
3281
+ * The fix is upstream: document these endpoints' response bodies in the owning
3282
+ * Nominal service's OpenAPI (then the registry entry can reference the generated
3283
+ * `*Response` type). Affected ops today: `GET_PERIODS`, `GET_PERIOD_INSTANCE`,
3284
+ * `GET_PERIOD_INSTANCE_BY_SLUG`, `POST_TASK_OUTPUT`, `GET_TASK_INSTANCE`,
3285
+ * `GET_TASK_INSTANCES`, `GET_TASK_DEFINITION`, `GET_ACTIVITY_DEFINITION(S)`,
3286
+ * `GET_ACTIVITY_INSTANCE`, `GET_ACTIVITY_INSTANCE_TASKS`,
3287
+ * `GET_ACTIVITY_PERIOD_TASKS`.
3288
+ */
3289
+ type UntypedApiResponse = unknown;
3268
3290
  interface UploadPayload {
3269
3291
  buffer: ArrayBuffer;
3270
3292
  fileName: string;
@@ -3337,11 +3359,11 @@ interface RequestRegistry {
3337
3359
  };
3338
3360
  GET_PERIODS: {
3339
3361
  payload: Omit<GetPeriodInstancesApiActivityPeriodInstanceGetData, 'url'>;
3340
- data: unknown;
3362
+ data: UntypedApiResponse;
3341
3363
  };
3342
3364
  POST_TASK_OUTPUT: {
3343
3365
  payload: Omit<UpdateTaskInstanceApiActivityTaskInstanceTaskInstanceIdPutData, 'url'>;
3344
- data: unknown;
3366
+ data: UntypedApiResponse;
3345
3367
  };
3346
3368
  GET_DIMENSIONS: {
3347
3369
  payload: Omit<GetDimensionsApiAccountingDimensionGetData, 'url'>;
@@ -3357,7 +3379,7 @@ interface RequestRegistry {
3357
3379
  };
3358
3380
  GET_ACTIVITY_DEFINITIONS: {
3359
3381
  payload: Omit<GetActivityDefinitionsApiActivityActivityDefinitionGetData, 'url'>;
3360
- data: unknown;
3382
+ data: UntypedApiResponse;
3361
3383
  };
3362
3384
  GET_TASK_DEFINITIONS: {
3363
3385
  payload: Omit<GetAllTasksDefinitionsApiActivityTaskDefinitionGetData, 'url'>;
@@ -3365,7 +3387,7 @@ interface RequestRegistry {
3365
3387
  };
3366
3388
  GET_TASK_INSTANCES: {
3367
3389
  payload: Omit<GetAllTaskInstancesApiActivityTaskInstanceGetData, 'url'>;
3368
- data: unknown;
3390
+ data: UntypedApiResponse;
3369
3391
  };
3370
3392
  GET_FISCAL_CALENDARS: {
3371
3393
  payload: Omit<GetFiscalCalendarsBySubsidiaryApiPeriodManagerFiscalCalendarBySubsidiarySubsidiaryIdGetData, 'url'>;
@@ -3433,11 +3455,11 @@ interface RequestRegistry {
3433
3455
  };
3434
3456
  GET_PERIOD_INSTANCE: {
3435
3457
  payload: Omit<GetPeriodInstanceApiActivityPeriodInstancePeriodInstanceIdGetData, 'url'>;
3436
- data: unknown;
3458
+ data: UntypedApiResponse;
3437
3459
  };
3438
3460
  GET_PERIOD_INSTANCE_BY_SLUG: {
3439
3461
  payload: Omit<GetPeriodInstanceBySlugApiActivityPeriodInstanceBySlugPeriodDisplayIdGetData, 'url'>;
3440
- data: unknown;
3462
+ data: UntypedApiResponse;
3441
3463
  };
3442
3464
  GET_PERIOD_PROGRESS_BREAKDOWN: {
3443
3465
  payload: Omit<GetPeriodInstanceProgressBreakdownBySlugApiActivityPeriodInstanceBySlugPeriodDisplayIdProgressBreakdownGetData, 'url'>;
@@ -3445,7 +3467,7 @@ interface RequestRegistry {
3445
3467
  };
3446
3468
  GET_ACTIVITY_DEFINITION: {
3447
3469
  payload: Omit<GetActivityDefinitionByIdApiActivityActivityDefinitionActivityDefinitionIdGetData, 'url'>;
3448
- data: unknown;
3470
+ data: UntypedApiResponse;
3449
3471
  };
3450
3472
  GET_ACTIVITY_INSTANCES: {
3451
3473
  payload: Omit<GetActivityInstancesApiActivityActivityInstanceGetData, 'url'>;
@@ -3453,7 +3475,7 @@ interface RequestRegistry {
3453
3475
  };
3454
3476
  GET_ACTIVITY_INSTANCE: {
3455
3477
  payload: Omit<GetActivityInstanceApiActivityActivityInstanceActivityInstanceIdGetData, 'url'>;
3456
- data: unknown;
3478
+ data: UntypedApiResponse;
3457
3479
  };
3458
3480
  GET_ACTIVITY_INSTANCE_BY_PERIOD: {
3459
3481
  payload: Omit<GetActivityInstanceByPeriodApiActivityActivityInstanceByPeriodPeriodDisplayIdActivityDefinitionIdGetData, 'url'>;
@@ -3461,15 +3483,15 @@ interface RequestRegistry {
3461
3483
  };
3462
3484
  GET_ACTIVITY_INSTANCE_TASKS: {
3463
3485
  payload: Omit<GetTaskInstancesByActivityApiActivityActivityInstanceActivityInstanceIdTaskGetData, 'url'>;
3464
- data: unknown;
3486
+ data: UntypedApiResponse;
3465
3487
  };
3466
3488
  GET_ACTIVITY_PERIOD_TASKS: {
3467
3489
  payload: Omit<GetTaskInstancesByActivityPeriodApiActivityActivityInstanceByPeriodPeriodDisplayIdActivityDefinitionIdTaskGetData, 'url'>;
3468
- data: unknown;
3490
+ data: UntypedApiResponse;
3469
3491
  };
3470
3492
  GET_TASK_DEFINITION: {
3471
3493
  payload: Omit<GetTaskDefinitionByIdApiActivityTaskDefinitionTaskDefinitionIdGetData, 'url'>;
3472
- data: unknown;
3494
+ data: UntypedApiResponse;
3473
3495
  };
3474
3496
  CREATE_TASK_DEFINITION: {
3475
3497
  payload: Omit<CreateTaskDefinitionApiActivityTaskDefinitionPostData, 'url'>;
@@ -3485,7 +3507,7 @@ interface RequestRegistry {
3485
3507
  };
3486
3508
  GET_TASK_INSTANCE: {
3487
3509
  payload: Omit<GetTaskInstanceByIdApiActivityTaskInstanceTaskInstanceIdGetData, 'url'>;
3488
- data: unknown;
3510
+ data: UntypedApiResponse;
3489
3511
  };
3490
3512
  GET_TASK_INSTANCES_BY_FILTER: {
3491
3513
  payload: Omit<GetAllTaskInstancesByFilterApiActivityTaskInstanceQueryPostData, 'url'>;
@@ -3545,12 +3567,24 @@ type RequestHandlers = {
3545
3567
  * string-matching `error.message`. A failed Nominal API call rehydrates as the
3546
3568
  * {@link HttpBridgeError} subtype, which adds the HTTP `status`.
3547
3569
  *
3570
+ * SDK-originated codes you may also see: `'TIMEOUT'` (a request or the connect
3571
+ * handshake timed out), `'DESTROYED'` (the bridge was torn down mid-flight),
3572
+ * `'PARENT_ORIGIN_UNRESOLVED'` (no embedding origin could be resolved) and
3573
+ * `'SERVER_ENVIRONMENT'` (a browser-only method was called where there is no
3574
+ * `window` — e.g. during SSR / in a React Server Component / in a Worker).
3575
+ *
3576
+ * This class is safe to import from any environment (see the module header).
3577
+ *
3548
3578
  * @example
3549
3579
  * ```ts
3580
+ * import { BridgeError } from '@nominalso/vibe-bridge'
3581
+ *
3550
3582
  * try {
3551
3583
  * await bridge.getAccounts({})
3552
3584
  * } catch (err) {
3553
- * if (err instanceof BridgeError && err.code === 'RATE_LIMITED') {
3585
+ * // `instanceof` works within a single bundle; `isBridgeError` also works
3586
+ * // across independently-built server/client bundles.
3587
+ * if (BridgeError.isBridgeError(err) && err.code === 'RATE_LIMITED') {
3554
3588
  * // back off and retry
3555
3589
  * }
3556
3590
  * }
@@ -3559,6 +3593,13 @@ type RequestHandlers = {
3559
3593
  declare class BridgeError extends Error {
3560
3594
  readonly code: string;
3561
3595
  constructor(code: string, message: string);
3596
+ /**
3597
+ * Cross-realm-safe type guard. Prefer this over `instanceof BridgeError` when
3598
+ * an error may have been thrown by a differently-built copy of the SDK (e.g.
3599
+ * server bundle vs client bundle) — it matches on a process-global brand
3600
+ * rather than class identity.
3601
+ */
3602
+ static isBridgeError(err: unknown): err is BridgeError;
3562
3603
  }
3563
3604
  /**
3564
3605
  * A {@link BridgeError} for a failed Nominal API call. Its `code` is always
@@ -3568,10 +3609,12 @@ declare class BridgeError extends Error {
3568
3609
  *
3569
3610
  * @example
3570
3611
  * ```ts
3612
+ * import { HttpBridgeError } from '@nominalso/vibe-bridge'
3613
+ *
3571
3614
  * try {
3572
3615
  * await bridge.getAccount({ path: { account_id: 'missing' } })
3573
3616
  * } catch (err) {
3574
- * if (err instanceof HttpBridgeError && err.status === 404) {
3617
+ * if (HttpBridgeError.isHttpBridgeError(err) && err.status === 404) {
3575
3618
  * // handle not-found
3576
3619
  * }
3577
3620
  * }
@@ -3580,6 +3623,11 @@ declare class BridgeError extends Error {
3580
3623
  declare class HttpBridgeError extends BridgeError {
3581
3624
  readonly status: number;
3582
3625
  constructor(status: number, message: string);
3626
+ /**
3627
+ * Cross-realm-safe type guard (see {@link BridgeError.isBridgeError}). Returns
3628
+ * `true` only for `HttpBridgeError` instances, not plain `BridgeError`s.
3629
+ */
3630
+ static isHttpBridgeError(err: unknown): err is HttpBridgeError;
3583
3631
  }
3584
3632
 
3585
3633
  interface VibeApiClientOptions {
package/dist/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  // package.json
2
- var version = "0.5.0";
2
+ var version = "0.5.1";
3
3
 
4
4
  // ../protocol-types/dist/index.js
5
5
  function normalizeSubroute(subroute) {
@@ -30,20 +30,46 @@ function isBridgeMessage(data) {
30
30
  if (CORRELATED_KINDS_SET.has(d.kind) && typeof d.requestId !== "string") return false;
31
31
  return true;
32
32
  }
33
+ var BRIDGE_ERROR_BRAND = /* @__PURE__ */ Symbol.for("@nominalso/vibe-bridge:BridgeError");
34
+ var HTTP_BRIDGE_ERROR_BRAND = /* @__PURE__ */ Symbol.for("@nominalso/vibe-bridge:HttpBridgeError");
33
35
  var BridgeError = class extends Error {
34
36
  constructor(code, message) {
35
37
  super(message);
36
38
  this.code = code;
37
39
  this.name = "BridgeError";
38
40
  }
41
+ /**
42
+ * Cross-realm-safe type guard. Prefer this over `instanceof BridgeError` when
43
+ * an error may have been thrown by a differently-built copy of the SDK (e.g.
44
+ * server bundle vs client bundle) — it matches on a process-global brand
45
+ * rather than class identity.
46
+ */
47
+ static isBridgeError(err) {
48
+ return typeof err === "object" && err !== null && err[BRIDGE_ERROR_BRAND] === true;
49
+ }
39
50
  };
51
+ Object.defineProperty(BridgeError.prototype, BRIDGE_ERROR_BRAND, {
52
+ value: true,
53
+ enumerable: false
54
+ });
40
55
  var HttpBridgeError = class extends BridgeError {
41
56
  constructor(status, message) {
42
57
  super("REQUEST_FAILED", message);
43
58
  this.status = status;
44
59
  this.name = "HttpBridgeError";
45
60
  }
61
+ /**
62
+ * Cross-realm-safe type guard (see {@link BridgeError.isBridgeError}). Returns
63
+ * `true` only for `HttpBridgeError` instances, not plain `BridgeError`s.
64
+ */
65
+ static isHttpBridgeError(err) {
66
+ return typeof err === "object" && err !== null && err[HTTP_BRIDGE_ERROR_BRAND] === true;
67
+ }
46
68
  };
69
+ Object.defineProperty(HttpBridgeError.prototype, HTTP_BRIDGE_ERROR_BRAND, {
70
+ value: true,
71
+ enumerable: false
72
+ });
47
73
  function isOriginPattern(entry) {
48
74
  return entry.includes("*");
49
75
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nominalso/vibe-host",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "description": "Host-side SDK for embedding Nominal Vibe Apps — receives bridge requests over a typed postMessage protocol and dispatches them to Nominal APIs (used by nom-ui).",
5
5
  "license": "UNLICENSED",
6
6
  "homepage": "https://github.com/nominalso/vibe-apps-sdk#readme",