@zerotal/client 1.7.0 → 1.7.2

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/CHANGELOG.md CHANGED
@@ -8,6 +8,35 @@ follows the Zerotal monorepo's unified versioning.
8
8
 
9
9
  ## [Unreleased]
10
10
 
11
+ ### Fixed
12
+
13
+ - **The documented import could not be bundled for a browser.** `import { Socket } from
14
+ "@zerotal/client"` — the line the broadcasting guide taught — failed with `Browser build cannot
15
+ import() Bun builtin: "bun"`. The root entry also exports `ClientProvider`, which extends core's
16
+ `ServiceProvider`, which reaches `CommandRunner`, which reaches the built-in CLI commands, one of
17
+ which does `await import("bun")`. That is a *resolution*-time error, so tree-shaking never got the
18
+ chance to drop the half nobody in a browser wanted: one server-only export made the whole package
19
+ unusable in the environment it exists for.
20
+
21
+ `@zerotal/client` now resolves to a browser-safe entry under the `browser` export condition —
22
+ `Socket`, `ApiClient`, `CircuitBreaker`, `createApiClient` and their types, and none of the
23
+ server-side exports. Bun and Node consumers still get the full barrel, `ClientProvider` included,
24
+ so nothing about registering the package changes. `@zerotal/client/Socket` still works and is
25
+ still the leanest import when `Socket` is all you need; `ClientProvider` also gained an explicit
26
+ `./provider` subpath.
27
+
28
+ Two supporting changes: `createApiClient` moved out of `index.ts` into its own module, because a
29
+ browser entry re-exporting it from the barrel pulls the barrel back in — the first attempt at this
30
+ fix did exactly that and bundled straight back into the same error. And the modules a browser can
31
+ reach now import from narrow core subpaths (`@zerotal/core/errors`, `@zerotal/core/helpers`)
32
+ rather than the root, because importing *anything at all* from core's root is enough to poison a
33
+ browser bundle.
34
+
35
+ Guarded by a test that runs `Bun.build` with `target: "browser"` — no unit test can see this,
36
+ since every module imports fine under Bun — plus one that holds the browser entry in step with
37
+ the barrel, since two entry points means two places to remember to add an export to.
38
+
39
+
11
40
  ## [1.0.3] — 2026-08-07
12
41
 
13
42
  ### Changed
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zerotal/client",
3
- "version": "1.7.0",
3
+ "version": "1.7.2",
4
4
  "license": "MIT",
5
5
  "maturity": "stable",
6
6
  "private": false,
@@ -8,8 +8,12 @@
8
8
  "main": "./src/index.ts",
9
9
  "types": "./src/index.ts",
10
10
  "exports": {
11
- ".": "./src/index.ts",
12
- "./Socket": "./src/Socket.ts"
11
+ ".": {
12
+ "browser": "./src/browser.ts",
13
+ "default": "./src/index.ts"
14
+ },
15
+ "./Socket": "./src/Socket.ts",
16
+ "./provider": "./src/provider/ClientProvider.ts"
13
17
  },
14
18
  "files": [
15
19
  "CHANGELOG.md",
@@ -31,7 +35,7 @@
31
35
  "typecheck": "tsc --noEmit"
32
36
  },
33
37
  "dependencies": {
34
- "@zerotal/core": "1.7.0"
38
+ "@zerotal/core": "1.7.2"
35
39
  },
36
40
  "devDependencies": {
37
41
  "typescript": "^5.8.0"
@@ -1,4 +1,4 @@
1
- import { ZerotalError } from "@zerotal/core";
1
+ import { ZerotalError } from "@zerotal/core/errors";
2
2
  import { ApiClientError } from "./ApiClient.ts";
3
3
 
4
4
  // ── Types ─────────────────────────────────────────────────────────────────────
package/src/Socket.ts CHANGED
@@ -4,7 +4,7 @@
4
4
  // broadcasting protocol (the `ws` / `redis` drivers) and exposes a familiar
5
5
  // realtime-client API — the same `channel()/private()/join()/leave()` +
6
6
  // `listen()/here()/joining()/leaving()` surface — so it works with `@zerotal/flow`'s
7
- // `@on('echo:…')` listeners with zero external dependencies.
7
+ // `@on('socket:…')` listeners with zero external dependencies.
8
8
  //
9
9
  // import { Socket } from "@zerotal/client";
10
10
  //
@@ -335,14 +335,14 @@ export class Socket {
335
335
  return this._subscribe(wire, () => new PresenceChannel(wire, this)) as PresenceChannel;
336
336
  }
337
337
 
338
- /** Echo alias for {@link presence} (`window.Echo.join(...)`). */
338
+ /** Alias for {@link presence} (`window.Socket.join(...)`). */
339
339
  join(name: string): PresenceChannel {
340
340
  return this.presence(name);
341
341
  }
342
342
 
343
343
  /**
344
344
  * Leave a channel by its base name — unsubscribes the public, `private-`, and `presence-`
345
- * variants (Echo's `leave()` semantics).
345
+ * variants, which is what `leave()` means here.
346
346
  */
347
347
  leave(name: string): void {
348
348
  this.leaveChannel(name);
package/src/browser.ts ADDED
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The browser-safe half of this package.
3
+ *
4
+ * Resolved for `import … from "@zerotal/client"` under the `browser` export
5
+ * condition, so a bundler targeting a browser gets this file and a Bun/Node
6
+ * import gets `index.ts` unchanged. Nobody has to know: the documented import
7
+ * is the same either way.
8
+ *
9
+ * What it leaves out is `ClientProvider` and `ClientConfig` — the two things
10
+ * here that are genuinely server-side. `ClientProvider` extends core's
11
+ * `ServiceProvider`, which reaches `CommandRunner`, which reaches the built-in
12
+ * CLI commands, one of which does `await import("bun")`. That is a hard error in
13
+ * a browser build and it happens during *resolution*, so tree-shaking never gets
14
+ * a chance to drop the unused half. The whole package became unbundleable
15
+ * because of one export nobody in a browser wanted.
16
+ *
17
+ * The rule this encodes: `@zerotal/core`'s root entry is server-only. A module
18
+ * that can run in a browser imports from a narrow subpath — `@zerotal/core/errors`,
19
+ * `@zerotal/core/helpers` — and never from the root.
20
+ */
21
+ export type {
22
+ ApiRouteMap,
23
+ RouteShape,
24
+ HttpMethod,
25
+ PathParams,
26
+ ParamRecord,
27
+ PathsFor,
28
+ ResponseOf,
29
+ BodyOf,
30
+ QueryOf,
31
+ } from "./types.ts";
32
+
33
+ export { ApiClient, ApiClientError, ValidationError } from "./ApiClient.ts";
34
+ export type {
35
+ ApiClientConfig,
36
+ RequestConfig,
37
+ RequestInterceptor,
38
+ ResponseContext,
39
+ ResponseInterceptor,
40
+ ResponseMeta,
41
+ RequestOptions,
42
+ GetOptions,
43
+ MutationOptions,
44
+ TokenSource,
45
+ RetryOptions,
46
+ } from "./ApiClient.ts";
47
+
48
+ export { CircuitBreaker, CircuitBreakerOpenError } from "./CircuitBreaker.ts";
49
+ export type { CircuitBreakerOptions, CircuitState } from "./CircuitBreaker.ts";
50
+
51
+ export { Socket, Channel, PresenceChannel } from "./Socket.ts";
52
+ export type { SocketOptions, SocketState, SocketLike, PresenceMember } from "./Socket.ts";
53
+
54
+ export { createApiClient } from "./createApiClient.ts";
package/src/config.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { deepMerge } from "@zerotal/core";
1
+ import { deepMerge } from "@zerotal/core/helpers";
2
2
  import type { ApiClientConfig } from "./ApiClient.ts";
3
3
 
4
4
  export interface ClientConfigShape extends ApiClientConfig {
@@ -0,0 +1,36 @@
1
+ // ── Factory function ──────────────────────────────────────────────────────────
2
+ //
3
+ // Its own module rather than a member of `index.ts`, so the browser entry can
4
+ // re-export it without pulling the server half of the barrel back in. That is
5
+ // not hypothetical tidiness: `browser.ts` originally took it from `index.ts`,
6
+ // which re-imported `ClientProvider` and put the bundle straight back into the
7
+ // error this split exists to remove.
8
+
9
+ import { ApiClient } from "./ApiClient.ts";
10
+ import type { ApiRouteMap } from "./types.ts";
11
+ import type { ApiClientConfig } from "./ApiClient.ts";
12
+
13
+ /**
14
+ * Create a type-safe API client bound to your route map.
15
+ *
16
+ * @example
17
+ * // frontend/api.ts
18
+ * import { createApiClient } from '@zerotal/client';
19
+ * import type { Routes } from './routes';
20
+ *
21
+ * export const api = createApiClient<Routes>({
22
+ * baseUrl: '/api',
23
+ * headers: { 'X-Requested-With': 'XMLHttpRequest' },
24
+ * });
25
+ *
26
+ * // Anywhere in your UI:
27
+ * const user = await api.get('/users/{id}', { id: 1 });
28
+ * // ^? UserResource (inferred from Routes)
29
+ *
30
+ * const newUser = await api.post('/users', { name: 'Alice', email: 'alice@ex.com' });
31
+ */
32
+ export function createApiClient<Routes extends ApiRouteMap>(
33
+ config: ApiClientConfig = {},
34
+ ): ApiClient<Routes> {
35
+ return new ApiClient<Routes>(config);
36
+ }
package/src/errors.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { ZerotalError } from "@zerotal/core";
1
+ import { ZerotalError } from "@zerotal/core/errors";
2
2
 
3
3
  /**
4
4
  * Thrown for any non-2xx HTTP response.
package/src/index.ts CHANGED
@@ -36,33 +36,4 @@ export { ClientProvider, Client } from "./provider/ClientProvider.ts";
36
36
  export { ClientConfig } from "./config.ts";
37
37
  export type { ClientConfigShape } from "./config.ts";
38
38
 
39
- // ── Factory function ──────────────────────────────────────────────────────────
40
-
41
- import { ApiClient } from "./ApiClient.ts";
42
- import type { ApiRouteMap } from "./types.ts";
43
- import type { ApiClientConfig } from "./ApiClient.ts";
44
-
45
- /**
46
- * Create a type-safe API client bound to your route map.
47
- *
48
- * @example
49
- * // frontend/api.ts
50
- * import { createApiClient } from '@zerotal/client';
51
- * import type { Routes } from './routes';
52
- *
53
- * export const api = createApiClient<Routes>({
54
- * baseUrl: '/api',
55
- * headers: { 'X-Requested-With': 'XMLHttpRequest' },
56
- * });
57
- *
58
- * // Anywhere in your UI:
59
- * const user = await api.get('/users/{id}', { id: 1 });
60
- * // ^? UserResource (inferred from Routes)
61
- *
62
- * const newUser = await api.post('/users', { name: 'Alice', email: 'alice@ex.com' });
63
- */
64
- export function createApiClient<Routes extends ApiRouteMap>(
65
- config: ApiClientConfig = {},
66
- ): ApiClient<Routes> {
67
- return new ApiClient<Routes>(config);
68
- }
39
+ export { createApiClient } from "./createApiClient.ts";