@effectstream/frontend-sdk 0.100.21 → 0.100.23

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.
Files changed (2) hide show
  1. package/build.ts +80 -36
  2. package/package.json +2 -2
package/build.ts CHANGED
@@ -1,50 +1,94 @@
1
1
  import { resolve, dirname } from "path";
2
2
 
3
- const externalDeps = new Set<string>();
4
- const visited = new Set<string>();
3
+ /**
4
+ * Walk the dependency tree rooted at `entryPkgPath` and decide what stays
5
+ * external in the browser bundle.
6
+ *
7
+ * Rules:
8
+ * - Internal `@effectstream/*` *dependencies* are bundled (we recurse into them
9
+ * so the SDK ships self-contained), and their third-party deps are marked
10
+ * external.
11
+ * - Every `peerDependency` / `optionalDependency` is marked external — these are
12
+ * provided by the consumer at runtime, never bundled. This includes
13
+ * `@effectstream/*` peers. It is the critical rule: `@effectstream/wallets`
14
+ * declares `@effectstream/midnight-contracts` as an OPTIONAL peer dep and
15
+ * reaches it only via `import("@effectstream/midnight-contracts/wallet-info")`.
16
+ * That module is node-only (`node:util` `parseArgs`, `node:fs`); bundling it
17
+ * into a `target: "browser"` build fails with
18
+ * "Browser polyfill for module 'node:util' doesn't have a matching export
19
+ * named 'parseArgs'". Externalizing keeps the dynamic import as a runtime
20
+ * import the consumer's bundler resolves (or the source's `.catch()` handles
21
+ * when absent).
22
+ */
23
+ export function collectExternals(entryPkgPath: string): Set<string> {
24
+ const externalDeps = new Set<string>();
25
+ const visited = new Set<string>();
5
26
 
6
- function collectExternals(pkgPath: string) {
7
- if (visited.has(pkgPath)) return;
8
- visited.add(pkgPath);
27
+ function walk(pkgPath: string) {
28
+ if (visited.has(pkgPath)) return;
29
+ visited.add(pkgPath);
9
30
 
10
- const pkg = require(pkgPath);
11
- for (const name of Object.keys(pkg.dependencies ?? {})) {
12
- if (!name.startsWith("@effectstream/")) {
31
+ const pkg = require(pkgPath);
32
+
33
+ // Peer + optional deps are never bundled — add the bare name AND a subpath
34
+ // wildcard so subpath imports (e.g. `@effectstream/midnight-contracts/wallet-info`)
35
+ // stay external too.
36
+ for (const name of [
37
+ ...Object.keys(pkg.peerDependencies ?? {}),
38
+ ...Object.keys(pkg.optionalDependencies ?? {}),
39
+ ]) {
13
40
  externalDeps.add(name);
14
- } else {
15
- try {
16
- const resolved = require.resolve(name + "/package.json", {
17
- paths: [dirname(pkgPath)],
18
- });
19
- collectExternals(resolved);
20
- } catch {
21
- // workspace package not resolvable, skip
41
+ externalDeps.add(name + "/*");
42
+ }
43
+
44
+ for (const name of Object.keys(pkg.dependencies ?? {})) {
45
+ if (!name.startsWith("@effectstream/")) {
46
+ externalDeps.add(name);
47
+ } else {
48
+ try {
49
+ const resolved = require.resolve(name + "/package.json", {
50
+ paths: [dirname(pkgPath)],
51
+ });
52
+ walk(resolved);
53
+ } catch {
54
+ // workspace package not resolvable, skip
55
+ }
22
56
  }
23
57
  }
24
58
  }
25
- // Peer deps are never bundled — treat all of them as external.
26
- for (const name of Object.keys(pkg.peerDependencies ?? {})) {
27
- externalDeps.add(name);
28
- }
59
+
60
+ walk(entryPkgPath);
61
+ return externalDeps;
29
62
  }
30
63
 
31
- collectExternals(resolve(import.meta.dir, "package.json"));
64
+ /** Build the browser bundle for `@effectstream/frontend-sdk`. */
65
+ export async function buildFrontend() {
66
+ const externalDeps = collectExternals(resolve(import.meta.dir, "package.json"));
32
67
 
33
- const result = await Bun.build({
34
- entrypoints: ["./src/mod.ts"],
35
- outdir: "./dist",
36
- target: "browser",
37
- format: "esm",
38
- external: [...externalDeps],
39
- });
68
+ const result = await Bun.build({
69
+ entrypoints: [resolve(import.meta.dir, "src/mod.ts")],
70
+ outdir: resolve(import.meta.dir, "dist"),
71
+ target: "browser",
72
+ format: "esm",
73
+ external: [...externalDeps],
74
+ });
40
75
 
41
- if (!result.success) {
42
- console.error("Build failed:");
43
- for (const log of result.logs) {
44
- console.error(log);
45
- }
46
- process.exit(1);
76
+ return { result, externalDeps };
47
77
  }
48
78
 
49
- console.log("Built frontend to dist/");
50
- console.log("External deps:", [...externalDeps].sort().join(", "));
79
+ // Only run the build when invoked as a script (`bun run build.ts`), not when
80
+ // imported by tests.
81
+ if (import.meta.main) {
82
+ const { result, externalDeps } = await buildFrontend();
83
+
84
+ if (!result.success) {
85
+ console.error("Build failed:");
86
+ for (const log of result.logs) {
87
+ console.error(log);
88
+ }
89
+ process.exit(1);
90
+ }
91
+
92
+ console.log("Built frontend to dist/");
93
+ console.log("External deps:", [...externalDeps].sort().join(", "));
94
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effectstream/frontend-sdk",
3
- "version": "0.100.21",
3
+ "version": "0.100.23",
4
4
  "license": "MIT",
5
5
  "homepage": "https://effectstream.github.io/docs/",
6
6
  "repository": {
@@ -27,7 +27,7 @@
27
27
  "build": "bun run build.ts"
28
28
  },
29
29
  "dependencies": {
30
- "@effectstream/wallets": "0.100.21"
30
+ "@effectstream/wallets": "0.100.23"
31
31
  },
32
32
  "description": "React frontend SDK for EffectStream"
33
33
  }