From 3e8358b733fe9296daee8cfd391470284d126526 Mon Sep 17 00:00:00 2001 From: Andy Bevan Date: Fri, 17 Jul 2026 10:08:10 -0400 Subject: [PATCH 1/3] fix(build): only shim node:url/path/module in ESM files that need them MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The tsup ESM banner (node:url/node:path/node:module + __dirname/__filename/ require shims) was applied unconditionally via esbuildOptions to every .mjs output, including pure-data files like enums.generated.mjs that never touch those globals. Strict browser bundlers (Vite, esbuild --platform=browser) can't resolve real Node built-ins, so importing @adcp/sdk/enums or other lean entry points broke bundling for browser consumers. Replace the blanket banner with an esbuild onLoad plugin that only prepends the shim to files whose transpiled body actually references __dirname/__filename/require (11 of 486 files) — detected via a throwaway transformSync so comments merely mentioning "require()" don't false-positive. Runs pre-transform so sourcemaps stay accurate. Add a browser-platform esbuild bundle check to verify-package.mjs so this class of regression fails CI going forward. Fixes #2364 --- .../tsup-conditional-node-shim-banner.md | 5 + package-lock.json | 619 +++++++++--------- package.json | 1 + scripts/verify-package.mjs | 23 +- tsup.config.ts | 62 +- 5 files changed, 381 insertions(+), 329 deletions(-) create mode 100644 .changeset/tsup-conditional-node-shim-banner.md diff --git a/.changeset/tsup-conditional-node-shim-banner.md b/.changeset/tsup-conditional-node-shim-banner.md new file mode 100644 index 000000000..7adde22d9 --- /dev/null +++ b/.changeset/tsup-conditional-node-shim-banner.md @@ -0,0 +1,5 @@ +--- +"@adcp/sdk": patch +--- + +Fix: the ESM build no longer injects the `node:url`/`node:path`/`node:module` shim banner into every `.mjs` file. Only the (11) files that actually reference `__dirname`, `__filename`, or `require` in their body get it now; pure-data and pure-logic modules — including `enums.generated.mjs`, `inline-enums.generated.mjs`, and everything reachable from the zod-free `./enums` entry point — no longer carry dead Node-only imports that broke strict browser bundlers (Vite, `esbuild --platform=browser`). diff --git a/package-lock.json b/package-lock.json index ec78d0014..4d0909925 100644 --- a/package-lock.json +++ b/package-lock.json @@ -44,6 +44,7 @@ "@types/pg": "^8.20.0", "@types/tar": "^6.1.13", "actionlint": "^2.0.6", + "esbuild": "^0.27.0", "esbuild-fix-imports-plugin": "^1.0.23", "eslint": "^10.0.3", "json-schema-to-typescript": "^15.0.4", @@ -901,9 +902,9 @@ } }, "node_modules/@esbuild/aix-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", - "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", + "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", "cpu": [ "ppc64" ], @@ -918,9 +919,9 @@ } }, "node_modules/@esbuild/android-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", - "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", + "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", "cpu": [ "arm" ], @@ -935,9 +936,9 @@ } }, "node_modules/@esbuild/android-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", - "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", + "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", "cpu": [ "arm64" ], @@ -952,9 +953,9 @@ } }, "node_modules/@esbuild/android-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", - "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", + "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", "cpu": [ "x64" ], @@ -969,9 +970,9 @@ } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", - "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", + "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", "cpu": [ "arm64" ], @@ -986,9 +987,9 @@ } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", - "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", + "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", "cpu": [ "x64" ], @@ -1003,9 +1004,9 @@ } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", - "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", + "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", "cpu": [ "arm64" ], @@ -1020,9 +1021,9 @@ } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", - "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", + "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", "cpu": [ "x64" ], @@ -1037,9 +1038,9 @@ } }, "node_modules/@esbuild/linux-arm": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", - "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", + "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", "cpu": [ "arm" ], @@ -1054,9 +1055,9 @@ } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", - "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", + "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", "cpu": [ "arm64" ], @@ -1071,9 +1072,9 @@ } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", - "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", + "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", "cpu": [ "ia32" ], @@ -1088,9 +1089,9 @@ } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", - "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", + "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", "cpu": [ "loong64" ], @@ -1105,9 +1106,9 @@ } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", - "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", + "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", "cpu": [ "mips64el" ], @@ -1122,9 +1123,9 @@ } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", - "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", + "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", "cpu": [ "ppc64" ], @@ -1139,9 +1140,9 @@ } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", - "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", + "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", "cpu": [ "riscv64" ], @@ -1156,9 +1157,9 @@ } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", - "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", + "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", "cpu": [ "s390x" ], @@ -1173,9 +1174,9 @@ } }, "node_modules/@esbuild/linux-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", - "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", + "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", "cpu": [ "x64" ], @@ -1190,9 +1191,9 @@ } }, "node_modules/@esbuild/netbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", - "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", + "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", "cpu": [ "arm64" ], @@ -1207,9 +1208,9 @@ } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", - "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", + "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", "cpu": [ "x64" ], @@ -1224,9 +1225,9 @@ } }, "node_modules/@esbuild/openbsd-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", - "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", + "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", "cpu": [ "arm64" ], @@ -1241,9 +1242,9 @@ } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", - "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", + "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", "cpu": [ "x64" ], @@ -1258,9 +1259,9 @@ } }, "node_modules/@esbuild/openharmony-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", - "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", + "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", "cpu": [ "arm64" ], @@ -1275,9 +1276,9 @@ } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", - "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", + "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", "cpu": [ "x64" ], @@ -1292,9 +1293,9 @@ } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", - "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", + "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", "cpu": [ "arm64" ], @@ -1309,9 +1310,9 @@ } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", - "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", + "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", "cpu": [ "ia32" ], @@ -1326,9 +1327,9 @@ } }, "node_modules/@esbuild/win32-x64": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", - "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", + "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", "cpu": [ "x64" ], @@ -4133,9 +4134,9 @@ } }, "node_modules/esbuild": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", - "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", + "version": "0.27.7", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", + "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -4146,32 +4147,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.28.1", - "@esbuild/android-arm": "0.28.1", - "@esbuild/android-arm64": "0.28.1", - "@esbuild/android-x64": "0.28.1", - "@esbuild/darwin-arm64": "0.28.1", - "@esbuild/darwin-x64": "0.28.1", - "@esbuild/freebsd-arm64": "0.28.1", - "@esbuild/freebsd-x64": "0.28.1", - "@esbuild/linux-arm": "0.28.1", - "@esbuild/linux-arm64": "0.28.1", - "@esbuild/linux-ia32": "0.28.1", - "@esbuild/linux-loong64": "0.28.1", - "@esbuild/linux-mips64el": "0.28.1", - "@esbuild/linux-ppc64": "0.28.1", - "@esbuild/linux-riscv64": "0.28.1", - "@esbuild/linux-s390x": "0.28.1", - "@esbuild/linux-x64": "0.28.1", - "@esbuild/netbsd-arm64": "0.28.1", - "@esbuild/netbsd-x64": "0.28.1", - "@esbuild/openbsd-arm64": "0.28.1", - "@esbuild/openbsd-x64": "0.28.1", - "@esbuild/openharmony-arm64": "0.28.1", - "@esbuild/sunos-x64": "0.28.1", - "@esbuild/win32-arm64": "0.28.1", - "@esbuild/win32-ia32": "0.28.1", - "@esbuild/win32-x64": "0.28.1" + "@esbuild/aix-ppc64": "0.27.7", + "@esbuild/android-arm": "0.27.7", + "@esbuild/android-arm64": "0.27.7", + "@esbuild/android-x64": "0.27.7", + "@esbuild/darwin-arm64": "0.27.7", + "@esbuild/darwin-x64": "0.27.7", + "@esbuild/freebsd-arm64": "0.27.7", + "@esbuild/freebsd-x64": "0.27.7", + "@esbuild/linux-arm": "0.27.7", + "@esbuild/linux-arm64": "0.27.7", + "@esbuild/linux-ia32": "0.27.7", + "@esbuild/linux-loong64": "0.27.7", + "@esbuild/linux-mips64el": "0.27.7", + "@esbuild/linux-ppc64": "0.27.7", + "@esbuild/linux-riscv64": "0.27.7", + "@esbuild/linux-s390x": "0.27.7", + "@esbuild/linux-x64": "0.27.7", + "@esbuild/netbsd-arm64": "0.27.7", + "@esbuild/netbsd-x64": "0.27.7", + "@esbuild/openbsd-arm64": "0.27.7", + "@esbuild/openbsd-x64": "0.27.7", + "@esbuild/openharmony-arm64": "0.27.7", + "@esbuild/sunos-x64": "0.27.7", + "@esbuild/win32-arm64": "0.27.7", + "@esbuild/win32-ia32": "0.27.7", + "@esbuild/win32-x64": "0.27.7" } }, "node_modules/esbuild-fix-imports-plugin": { @@ -8307,44 +8308,93 @@ } } }, - "node_modules/tsup/node_modules/@esbuild/aix-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.7.tgz", - "integrity": "sha512-EKX3Qwmhz1eMdEJokhALr0YiD0lhQNwDqkPYyPhiSwKrh7/4KRjQc04sZ8db+5DVVnZ1LmbNDI1uAMPEUBnQPg==", - "cpu": [ - "ppc64" - ], + "node_modules/tsup/node_modules/tinyexec": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", + "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } + "license": "MIT" }, - "node_modules/tsup/node_modules/@esbuild/android-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.7.tgz", - "integrity": "sha512-jbPXvB4Yj2yBV7HUfE2KHe4GJX51QplCN1pGbYjvsyCZbQmies29EoJbkEc+vYuU5o45AfQn37vZlyXy4YJ8RQ==", - "cpu": [ - "arm" - ], + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], + "dependencies": { + "tslib": "^1.8.1" + }, "engines": { - "node": ">=18" + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" } }, - "node_modules/tsup/node_modules/@esbuild/android-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.7.tgz", - "integrity": "sha512-62dPZHpIXzvChfvfLJow3q5dDtiNMkwiRzPylSCfriLvZeq0a1bWChrGx/BbUbPwOrsWKMn8idSllklzBy+dgQ==", + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/tsx": { + "version": "4.22.2", + "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.2.tgz", + "integrity": "sha512-6w9FwtT8WQqRAyTNR+Z+86kghRqpmOLjXUrBlBT6T+CQGDuIMm0VmAqaFUFBIeKDTGobE6/YSigZYLeomzBaRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "~0.28.0" + }, + "bin": { + "tsx": "dist/cli.mjs" + }, + "engines": { + "node": ">=18.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + } + }, + "node_modules/tsx/node_modules/@esbuild/aix-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.28.1.tgz", + "integrity": "sha512-Svl7tq8k/08+p6CXPpRjQ1fKX+1odH/BQbb48fV6fj3CWHhsoIOoY87w1oHXm0qEpkIK3ZfVgp0hed3XBXzXMQ==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.28.1.tgz", + "integrity": "sha512-0k2F129Xdio1TdJfzJ8sy1Q47vUD2NnwdhiAf7drUN1EBTfPf4hsFCtmMgu/6m8JSzsBrlmVjudMBQqOfG8usQ==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/tsx/node_modules/@esbuild/android-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.28.1.tgz", + "integrity": "sha512-34EGEbCIAgosYz6goLcopX6Mo7NyGv9tfwEM2/7Ce2VcVRk568iSvniGWcUXIy7wEDR1wzolcxcriFVrWYcwBg==", "cpu": [ "arm64" ], @@ -8358,10 +8408,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/android-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.7.tgz", - "integrity": "sha512-x5VpMODneVDb70PYV2VQOmIUUiBtY3D3mPBG8NxVk5CogneYhkR7MmM3yR/uMdITLrC1ml/NV1rj4bMJuy9MCg==", + "node_modules/tsx/node_modules/@esbuild/android-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.28.1.tgz", + "integrity": "sha512-dbwY7ltSMDWsRatcRpCnES4F+im88OCUgGZjy52shC7GqHRE/cYlxNbB4Z4UpJswpcc4Qxd2oE/ufM0p61IKng==", "cpu": [ "x64" ], @@ -8375,10 +8425,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/darwin-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.7.tgz", - "integrity": "sha512-5lckdqeuBPlKUwvoCXIgI2D9/ABmPq3Rdp7IfL70393YgaASt7tbju3Ac+ePVi3KDH6N2RqePfHnXkaDtY9fkw==", + "node_modules/tsx/node_modules/@esbuild/darwin-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.28.1.tgz", + "integrity": "sha512-TZbWkQY7kvTAXbXUT7uVACR5cMHsDiSz9z7ZKAX/RTq/WJEk3QyRr0wZpNhBDX+/0CtdqUIJlOiodQcta6tY3Q==", "cpu": [ "arm64" ], @@ -8392,10 +8442,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/darwin-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.7.tgz", - "integrity": "sha512-rYnXrKcXuT7Z+WL5K980jVFdvVKhCHhUwid+dDYQpH+qu+TefcomiMAJpIiC2EM3Rjtq0sO3StMV/+3w3MyyqQ==", + "node_modules/tsx/node_modules/@esbuild/darwin-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.28.1.tgz", + "integrity": "sha512-zfdzgK9ACBNZLI/CyHTOx81SyNbM6YXn7rxSgX97VjyiPl9W1i4Ka4fgKECEoFCKGpvBj5qArWIGgQjOwkgskQ==", "cpu": [ "x64" ], @@ -8409,10 +8459,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/freebsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.7.tgz", - "integrity": "sha512-B48PqeCsEgOtzME2GbNM2roU29AMTuOIN91dsMO30t+Ydis3z/3Ngoj5hhnsOSSwNzS+6JppqWsuhTp6E82l2w==", + "node_modules/tsx/node_modules/@esbuild/freebsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.28.1.tgz", + "integrity": "sha512-wG2EA8ENdEI0qhkSZMjfqrdY+ziCYCPMmtZjjIwOmXFjmyzEHn+UUxk5of+SYsjtfs3VpnlC7QLzSI5hY/rOAw==", "cpu": [ "arm64" ], @@ -8426,10 +8476,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/freebsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.7.tgz", - "integrity": "sha512-jOBDK5XEjA4m5IJK3bpAQF9/Lelu/Z9ZcdhTRLf4cajlB+8VEhFFRjWgfy3M1O4rO2GQ/b2dLwCUGpiF/eATNQ==", + "node_modules/tsx/node_modules/@esbuild/freebsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.28.1.tgz", + "integrity": "sha512-i7dZ9vQgnvSCzi/rYCXNgtF/U+eKZNJBzu3eTQbRgHnM7tNSizLOkRFAl3qzVc/Op/u5YkHHa4pf/3DOYHthLQ==", "cpu": [ "x64" ], @@ -8443,10 +8493,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/linux-arm": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.7.tgz", - "integrity": "sha512-RkT/YXYBTSULo3+af8Ib0ykH8u2MBh57o7q/DAs3lTJlyVQkgQvlrPTnjIzzRPQyavxtPtfg0EopvDyIt0j1rA==", + "node_modules/tsx/node_modules/@esbuild/linux-arm": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.28.1.tgz", + "integrity": "sha512-qVXBOHQS+d5Y722GwJzJUtOLlX7km3CraOaGormF1pDtPd2C/l1SHRPgjLunLGe51Sh5YYWKMFDyV4SxgMQYTQ==", "cpu": [ "arm" ], @@ -8460,10 +8510,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/linux-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.7.tgz", - "integrity": "sha512-RZPHBoxXuNnPQO9rvjh5jdkRmVizktkT7TCDkDmQ0W2SwHInKCAV95GRuvdSvA7w4VMwfCjUiPwDi0ZO6Nfe9A==", + "node_modules/tsx/node_modules/@esbuild/linux-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.28.1.tgz", + "integrity": "sha512-yHs+0uc8+nvEAfAfxrWQKK5peSNzBc4PegcMO0EJ2hT71uA7vB8Ihg2e77R2P7SG5uYjPbHlLLmve4LLLRCf0g==", "cpu": [ "arm64" ], @@ -8477,10 +8527,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/linux-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.7.tgz", - "integrity": "sha512-GA48aKNkyQDbd3KtkplYWT102C5sn/EZTY4XROkxONgruHPU72l+gW+FfF8tf2cFjeHaRbWpOYa/uRBz/Xq1Pg==", + "node_modules/tsx/node_modules/@esbuild/linux-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.28.1.tgz", + "integrity": "sha512-d1z4ZuP0ajrfz/FhGT4vv278rX8KnPPJx8i5+AtK7TYbx9Le9F1hyzurZpkEyjkGa9dUGhQow4C1NmeGvqxN2w==", "cpu": [ "ia32" ], @@ -8494,10 +8544,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/linux-loong64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.7.tgz", - "integrity": "sha512-a4POruNM2oWsD4WKvBSEKGIiWQF8fZOAsycHOt6JBpZ+JN2n2JH9WAv56SOyu9X5IqAjqSIPTaJkqN8F7XOQ5Q==", + "node_modules/tsx/node_modules/@esbuild/linux-loong64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.28.1.tgz", + "integrity": "sha512-M5sRjUVZrkm1OAPR3dlOYzNmN+loZKGVi1VUQGrwuqLcbR6qeAz+famMhjASeH3YVKvZz+zT1jlh/keC3Rj/lg==", "cpu": [ "loong64" ], @@ -8511,10 +8561,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/linux-mips64el": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.7.tgz", - "integrity": "sha512-KabT5I6StirGfIz0FMgl1I+R1H73Gp0ofL9A3nG3i/cYFJzKHhouBV5VWK1CSgKvVaG4q1RNpCTR2LuTVB3fIw==", + "node_modules/tsx/node_modules/@esbuild/linux-mips64el": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.28.1.tgz", + "integrity": "sha512-mRObBZeHh2OxcBFPWE/FjylkRgZdYuiTR3vaTozquCGOH14iP9oN4x4Ge81CoIDYQrXmIxpFumJBu5MtZpnQJQ==", "cpu": [ "mips64el" ], @@ -8528,10 +8578,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/linux-ppc64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.7.tgz", - "integrity": "sha512-gRsL4x6wsGHGRqhtI+ifpN/vpOFTQtnbsupUF5R5YTAg+y/lKelYR1hXbnBdzDjGbMYjVJLJTd2OFmMewAgwlQ==", + "node_modules/tsx/node_modules/@esbuild/linux-ppc64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.28.1.tgz", + "integrity": "sha512-slScBsMAb3GFDcdrCgLwZtPYRoH2H/youv10QiZyRjmsP48fznoveWytSgCI/R0ZcUgpc0ZhIUEx6LHts8yrfQ==", "cpu": [ "ppc64" ], @@ -8545,10 +8595,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/linux-riscv64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.7.tgz", - "integrity": "sha512-hL25LbxO1QOngGzu2U5xeXtxXcW+/GvMN3ejANqXkxZ/opySAZMrc+9LY/WyjAan41unrR3YrmtTsUpwT66InQ==", + "node_modules/tsx/node_modules/@esbuild/linux-riscv64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.28.1.tgz", + "integrity": "sha512-kw0owk1o0GFETUJyW0jc0G4Yzs0BHZn0JDZ8JRT088vjJYX777BAs1fDGxAC+q831qOs2DTC96mNsG2opdfyyQ==", "cpu": [ "riscv64" ], @@ -8562,10 +8612,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/linux-s390x": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.7.tgz", - "integrity": "sha512-2k8go8Ycu1Kb46vEelhu1vqEP+UeRVj2zY1pSuPdgvbd5ykAw82Lrro28vXUrRmzEsUV0NzCf54yARIK8r0fdw==", + "node_modules/tsx/node_modules/@esbuild/linux-s390x": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.28.1.tgz", + "integrity": "sha512-/lAIjX8aYFRByhh6L5rYtPEDRqa9de/4V/juOXcta5frjvzXO4/sqEtyytse0g3zZFuWu5cDN0MkLz2qRDD2Ag==", "cpu": [ "s390x" ], @@ -8579,10 +8629,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/linux-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.7.tgz", - "integrity": "sha512-hzznmADPt+OmsYzw1EE33ccA+HPdIqiCRq7cQeL1Jlq2gb1+OyWBkMCrYGBJ+sxVzve2ZJEVeePbLM2iEIZSxA==", + "node_modules/tsx/node_modules/@esbuild/linux-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.28.1.tgz", + "integrity": "sha512-u/anNYF2mmVOEDwLtnQ1wOr3EZ9sTNGLWrsYGYwHWzGA3Si84IOkHXlbWTD1NB+9/1lcnweYKO54uhxZydNzfA==", "cpu": [ "x64" ], @@ -8596,10 +8646,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/netbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.7.tgz", - "integrity": "sha512-b6pqtrQdigZBwZxAn1UpazEisvwaIDvdbMbmrly7cDTMFnw/+3lVxxCTGOrkPVnsYIosJJXAsILG9XcQS+Yu6w==", + "node_modules/tsx/node_modules/@esbuild/netbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.28.1.tgz", + "integrity": "sha512-oks0DYbLwWMmaakTsCb+zL4E+aHRVLom9IJZOAthMQEPiQmydXHkziYEsGYRx0uNV/IjEKGAV941JzH02pflqw==", "cpu": [ "arm64" ], @@ -8613,10 +8663,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/netbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.7.tgz", - "integrity": "sha512-OfatkLojr6U+WN5EDYuoQhtM+1xco+/6FSzJJnuWiUw5eVcicbyK3dq5EeV/QHT1uy6GoDhGbFpprUiHUYggrw==", + "node_modules/tsx/node_modules/@esbuild/netbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.28.1.tgz", + "integrity": "sha512-aeL6lAnN89Hz43Mlh1G8ARasbuoYvSITDEx0tHh5b7jJnHcssqgjy9Yx430GDpmCa6OyrKoS0aNRjKundRizGg==", "cpu": [ "x64" ], @@ -8630,10 +8680,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/openbsd-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.7.tgz", - "integrity": "sha512-AFuojMQTxAz75Fo8idVcqoQWEHIXFRbOc1TrVcFSgCZtQfSdc1RXgB3tjOn/krRHENUB4j00bfGjyl2mJrU37A==", + "node_modules/tsx/node_modules/@esbuild/openbsd-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.28.1.tgz", + "integrity": "sha512-MEFJe5C3R8pwXdZ5Y21oo6m7ePiS0d9pWucn99O/wvyJZChoIQKrQDxKrGeW8F5+T0okTHesAmDeiHDTIq0V/Q==", "cpu": [ "arm64" ], @@ -8647,10 +8697,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/openbsd-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.7.tgz", - "integrity": "sha512-+A1NJmfM8WNDv5CLVQYJ5PshuRm/4cI6WMZRg1by1GwPIQPCTs1GLEUHwiiQGT5zDdyLiRM/l1G0Pv54gvtKIg==", + "node_modules/tsx/node_modules/@esbuild/openbsd-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.28.1.tgz", + "integrity": "sha512-i/ZLIOafE0Z8cI/XANJAixoJL/uRAoS2xOA3rb0xN+KK0K177cMAsQYkzHtBrtMXAKuAc7HGgcWiZ/sRC1Nxgw==", "cpu": [ "x64" ], @@ -8664,10 +8714,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/openharmony-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.7.tgz", - "integrity": "sha512-+KrvYb/C8zA9CU/g0sR6w2RBw7IGc5J2BPnc3dYc5VJxHCSF1yNMxTV5LQ7GuKteQXZtspjFbiuW5/dOj7H4Yw==", + "node_modules/tsx/node_modules/@esbuild/openharmony-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.28.1.tgz", + "integrity": "sha512-ge+Z7EXFNt2BO1oAMsVpiQ8EwndV9i1xXerAeTIK7AtPs3bKFXQM7nlRxDSIUIMeueR1CNXxqztLzdNeReKBJg==", "cpu": [ "arm64" ], @@ -8681,10 +8731,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/sunos-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.7.tgz", - "integrity": "sha512-ikktIhFBzQNt/QDyOL580ti9+5mL/YZeUPKU2ivGtGjdTYoqz6jObj6nOMfhASpS4GU4Q/Clh1QtxWAvcYKamA==", + "node_modules/tsx/node_modules/@esbuild/sunos-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.28.1.tgz", + "integrity": "sha512-BEjgtECkL3vY+SaSQ6nzVfiALUeFxpawyp8Jmf5PtYhf1Ug40N1h/hxlhts+f1FvSvarEigdxS3BlSMI2PJLcQ==", "cpu": [ "x64" ], @@ -8698,10 +8748,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/win32-arm64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.7.tgz", - "integrity": "sha512-7yRhbHvPqSpRUV7Q20VuDwbjW5kIMwTHpptuUzV+AA46kiPze5Z7qgt6CLCK3pWFrHeNfDd1VKgyP4O+ng17CA==", + "node_modules/tsx/node_modules/@esbuild/win32-arm64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.28.1.tgz", + "integrity": "sha512-lCv9eK/H6ZJWbE7bh2nw54CZ9M2nupBxJcTsdk/QQnWkdSjKGuxmmH8/GWrlT1eMmZfn4dGcCjRte397WqfQXA==", "cpu": [ "arm64" ], @@ -8715,10 +8765,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/win32-ia32": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.7.tgz", - "integrity": "sha512-SmwKXe6VHIyZYbBLJrhOoCJRB/Z1tckzmgTLfFYOfpMAx63BJEaL9ExI8x7v0oAO3Zh6D/Oi1gVxEYr5oUCFhw==", + "node_modules/tsx/node_modules/@esbuild/win32-ia32": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.28.1.tgz", + "integrity": "sha512-zvb/mB2bSCoJOpoCBgYKKpX6YM6mJBlBUVUtVj41DlZJVEB6/0CKlRYxP5wWl1C1ILiCoAU5wZZ4q1P3qeS6Eg==", "cpu": [ "ia32" ], @@ -8732,10 +8782,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/@esbuild/win32-x64": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.7.tgz", - "integrity": "sha512-56hiAJPhwQ1R4i+21FVF7V8kSD5zZTdHcVuRFMW0hn753vVfQN8xlx4uOPT4xoGH0Z/oVATuR82AiqSTDIpaHg==", + "node_modules/tsx/node_modules/@esbuild/win32-x64": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.28.1.tgz", + "integrity": "sha512-bm4Mowrv+GXMlpWX++EcXw/iLyd1o3+bJkC2DkWXYVvgZCqD/bSj9ctZeAMC3cIxgjRVR2Dufaiu4YPxr5gW1A==", "cpu": [ "x64" ], @@ -8749,10 +8799,10 @@ "node": ">=18" } }, - "node_modules/tsup/node_modules/esbuild": { - "version": "0.27.7", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.7.tgz", - "integrity": "sha512-IxpibTjyVnmrIQo5aqNpCgoACA/dTKLTlhMHihVHhdkxKyPO1uBBthumT0rdHmcsk9uMonIWS0m4FljWzILh3w==", + "node_modules/tsx/node_modules/esbuild": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.28.1.tgz", + "integrity": "sha512-HrJrvZv5ayxBzPfwphOoNzkzOIIlifzk0KJrGK2c8R4+LKpMtpYLQeUdjnwjWv/LZlkH2laZk+4w78pi99D4Vw==", "dev": true, "hasInstallScript": true, "license": "MIT", @@ -8763,81 +8813,32 @@ "node": ">=18" }, "optionalDependencies": { - "@esbuild/aix-ppc64": "0.27.7", - "@esbuild/android-arm": "0.27.7", - "@esbuild/android-arm64": "0.27.7", - "@esbuild/android-x64": "0.27.7", - "@esbuild/darwin-arm64": "0.27.7", - "@esbuild/darwin-x64": "0.27.7", - "@esbuild/freebsd-arm64": "0.27.7", - "@esbuild/freebsd-x64": "0.27.7", - "@esbuild/linux-arm": "0.27.7", - "@esbuild/linux-arm64": "0.27.7", - "@esbuild/linux-ia32": "0.27.7", - "@esbuild/linux-loong64": "0.27.7", - "@esbuild/linux-mips64el": "0.27.7", - "@esbuild/linux-ppc64": "0.27.7", - "@esbuild/linux-riscv64": "0.27.7", - "@esbuild/linux-s390x": "0.27.7", - "@esbuild/linux-x64": "0.27.7", - "@esbuild/netbsd-arm64": "0.27.7", - "@esbuild/netbsd-x64": "0.27.7", - "@esbuild/openbsd-arm64": "0.27.7", - "@esbuild/openbsd-x64": "0.27.7", - "@esbuild/openharmony-arm64": "0.27.7", - "@esbuild/sunos-x64": "0.27.7", - "@esbuild/win32-arm64": "0.27.7", - "@esbuild/win32-ia32": "0.27.7", - "@esbuild/win32-x64": "0.27.7" - } - }, - "node_modules/tsup/node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/tsutils": { - "version": "3.21.0", - "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", - "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", - "dev": true, - "license": "MIT", - "dependencies": { - "tslib": "^1.8.1" - }, - "engines": { - "node": ">= 6" - }, - "peerDependencies": { - "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" - } - }, - "node_modules/tsutils/node_modules/tslib": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", - "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", - "dev": true, - "license": "0BSD" - }, - "node_modules/tsx": { - "version": "4.22.2", - "resolved": "https://registry.npmjs.org/tsx/-/tsx-4.22.2.tgz", - "integrity": "sha512-6w9FwtT8WQqRAyTNR+Z+86kghRqpmOLjXUrBlBT6T+CQGDuIMm0VmAqaFUFBIeKDTGobE6/YSigZYLeomzBaRg==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "~0.28.0" - }, - "bin": { - "tsx": "dist/cli.mjs" - }, - "engines": { - "node": ">=18.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" + "@esbuild/aix-ppc64": "0.28.1", + "@esbuild/android-arm": "0.28.1", + "@esbuild/android-arm64": "0.28.1", + "@esbuild/android-x64": "0.28.1", + "@esbuild/darwin-arm64": "0.28.1", + "@esbuild/darwin-x64": "0.28.1", + "@esbuild/freebsd-arm64": "0.28.1", + "@esbuild/freebsd-x64": "0.28.1", + "@esbuild/linux-arm": "0.28.1", + "@esbuild/linux-arm64": "0.28.1", + "@esbuild/linux-ia32": "0.28.1", + "@esbuild/linux-loong64": "0.28.1", + "@esbuild/linux-mips64el": "0.28.1", + "@esbuild/linux-ppc64": "0.28.1", + "@esbuild/linux-riscv64": "0.28.1", + "@esbuild/linux-s390x": "0.28.1", + "@esbuild/linux-x64": "0.28.1", + "@esbuild/netbsd-arm64": "0.28.1", + "@esbuild/netbsd-x64": "0.28.1", + "@esbuild/openbsd-arm64": "0.28.1", + "@esbuild/openbsd-x64": "0.28.1", + "@esbuild/openharmony-arm64": "0.28.1", + "@esbuild/sunos-x64": "0.28.1", + "@esbuild/win32-arm64": "0.28.1", + "@esbuild/win32-ia32": "0.28.1", + "@esbuild/win32-x64": "0.28.1" } }, "node_modules/type-check": { diff --git a/package.json b/package.json index e9144f2ad..be2dc2b8c 100644 --- a/package.json +++ b/package.json @@ -615,6 +615,7 @@ "@types/pg": "^8.20.0", "@types/tar": "^6.1.13", "actionlint": "^2.0.6", + "esbuild": "^0.27.0", "esbuild-fix-imports-plugin": "^1.0.23", "eslint": "^10.0.3", "json-schema-to-typescript": "^15.0.4", diff --git a/scripts/verify-package.mjs b/scripts/verify-package.mjs index eeebee3ae..725b82ca0 100644 --- a/scripts/verify-package.mjs +++ b/scripts/verify-package.mjs @@ -132,7 +132,28 @@ try { console.log('šŸ” CJS require:'); run('node', ['smoke.cjs'], { cwd: tmpDir, stdio: 'inherit' }); - console.log('\nāœ… Package loads in both ESM and CJS with peer floors satisfied.'); + // `@adcp/sdk/enums` is documented as a lean, zod-free entry point safe for + // browser bundlers. Bundling it with `--platform=browser` catches + // Node-only imports (`node:url`/`node:path`/`node:module`, etc.) that + // esbuild's `--platform=node` and plain `node` execution above wouldn't — + // this is what would have caught adcp#2364 (an unconditional ESM banner + // dragging Node built-ins into every `.mjs`, including pure-data ones). + console.log('🌐 Browser bundle check (--platform=browser) for @adcp/sdk/enums:'); + writeFileSync( + path.join(tmpDir, 'smoke.browser.mjs'), + [ + "import { EventTypeValues } from '@adcp/sdk/enums';", + "if (EventTypeValues.length === 0) throw new Error('EventTypeValues is empty');", + ].join('\n') + ); + run( + path.join(REPO_ROOT, 'node_modules', '.bin', 'esbuild'), + ['smoke.browser.mjs', '--bundle', '--format=esm', '--platform=browser', '--outfile=smoke.browser.out.js'], + { cwd: tmpDir, stdio: 'inherit' } + ); + console.log(' browser bundle of @adcp/sdk/enums ok'); + + console.log('\nāœ… Package loads in both ESM and CJS with peer floors satisfied, and browser-bundles cleanly.'); } catch (err) { console.error('\nāŒ Package verification failed:'); console.error(err.message ?? err); diff --git a/tsup.config.ts b/tsup.config.ts index af3e4b14c..a732d086d 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -1,8 +1,46 @@ -import { existsSync } from 'node:fs'; +import { existsSync, readFileSync } from 'node:fs'; import * as nodePath from 'node:path'; +import { transformSync } from 'esbuild'; import { defineConfig } from 'tsup'; import { fixImportsPlugin } from 'esbuild-fix-imports-plugin'; +// Only files that actually reference `__dirname`/`__filename`/`require` in +// their body need the ESM shim below; injecting it into every ESM output +// (as a global esbuild `banner`) drags `node:url`/`node:path`/`node:module` +// imports into pure-data/pure-logic modules that never touch them, which a +// browser bundler can't resolve (adcp#2364). +// +// Runs pre-transform via `onLoad` — prepending to the TS source rather than +// the emitted JS — so esbuild's own sourcemap generation accounts for the +// added lines, matching what the (removed) `banner` option got for free. +// Detection uses a throwaway `transformSync` of the file (comments and types +// stripped) instead of matching the raw source, so a comment that merely +// mentions "require()" can't trigger a false positive. +function conditionalNodeShimPlugin() { + const banner = [ + "import { fileURLToPath as __adcpFileURLToPath } from 'node:url';", + "import { dirname as __adcpDirname } from 'node:path';", + "import { createRequire as __adcpCreateRequire } from 'node:module';", + 'const __filename = __adcpFileURLToPath(import.meta.url);', + 'const __dirname = __adcpDirname(__filename);', + 'const require = __adcpCreateRequire(import.meta.url);', + ].join('\n'); + const needsShim = /\b(__dirname|__filename)\b|\brequire\s*\(/; + + return { + name: 'conditional-node-shim', + setup(build: import('esbuild').PluginBuild) { + if (build.initialOptions.format !== 'esm') return; + build.onLoad({ filter: /\.ts$/ }, args => { + const source = readFileSync(args.path, 'utf8'); + const { code } = transformSync(source, { loader: 'ts', legalComments: 'none' }); + if (!needsShim.test(code)) return null; + return { contents: `${banner}\n${source}`, loader: 'ts' }; + }); + }, + }; +} + // Companion to `fixImportsPlugin`: that plugin rewrites static `from '...'` and // `require('...')` specifiers, but not dynamic `import('...')`. Under // `bundle: false` those stay extensionless, so a lazy `await import('../x')` @@ -75,28 +113,14 @@ export default defineConfig({ clean: true, dts: false, // Not tsup's `shims: true`: with many entries it emits `__dirname` once in a - // shared chunk (resolving to the chunk's dir, not each module's). The banner - // below is inlined into every ESM file, so `import.meta.url` — and therefore - // `__dirname` — is correct per file. CJS keeps the native globals. + // shared chunk (resolving to the chunk's dir, not each module's). The shim + // plugin below inlines it per file that needs it, so `import.meta.url` — + // and therefore `__dirname` — is correct per file. CJS keeps the native globals. shims: false, - esbuildOptions(options, context) { - if (context.format === 'esm') { - options.banner = { - js: [ - "import { fileURLToPath as __adcpFileURLToPath } from 'node:url';", - "import { dirname as __adcpDirname } from 'node:path';", - "import { createRequire as __adcpCreateRequire } from 'node:module';", - 'const __filename = __adcpFileURLToPath(import.meta.url);', - 'const __dirname = __adcpDirname(__filename);', - 'const require = __adcpCreateRequire(import.meta.url);', - ].join('\n'), - }; - } - }, // ESM → .mjs (the `import` condition), CJS → .js (the `require` condition and // the CLI's `require('../dist/lib/...')`). The package stays `type: commonjs`. outExtension({ format }) { return { js: format === 'esm' ? '.mjs' : '.js' }; }, - esbuildPlugins: [fixImportsPlugin(), fixDynamicImportExtensions()], + esbuildPlugins: [fixImportsPlugin(), fixDynamicImportExtensions(), conditionalNodeShimPlugin()], }); From 60154a6c557e3937014f55fc467ff1e173cc1779 Mon Sep 17 00:00:00 2001 From: Andy Bevan Date: Fri, 17 Jul 2026 10:45:45 -0400 Subject: [PATCH 2/3] fix(build): tighten node-shim detection, drop unused __filename MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two follow-ups from review: - require(...features) in SingleAgentClient.ts is a class method, not a call to the global require — the detection regex matched it anyway, giving that file the shim unnecessarily. Every real require() call in the codebase takes a string-literal module specifier, so require the match to have a following quote. - __filename is never read by any source file; it only existed as an intermediate step toward __dirname. Compute __dirname inline instead of binding an unused name. --- tsup.config.ts | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/tsup.config.ts b/tsup.config.ts index a732d086d..df085b67c 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -4,28 +4,31 @@ import { transformSync } from 'esbuild'; import { defineConfig } from 'tsup'; import { fixImportsPlugin } from 'esbuild-fix-imports-plugin'; -// Only files that actually reference `__dirname`/`__filename`/`require` in -// their body need the ESM shim below; injecting it into every ESM output -// (as a global esbuild `banner`) drags `node:url`/`node:path`/`node:module` -// imports into pure-data/pure-logic modules that never touch them, which a -// browser bundler can't resolve (adcp#2364). +// Only files that actually reference `__dirname` or `require` in their body +// need the ESM shim below (no source file reads bare `__filename`, so it's +// only an intermediate in computing `__dirname` from `import.meta.url`, not +// its own shim target); injecting it into every ESM output (as a global +// esbuild `banner`) drags `node:url`/`node:path`/`node:module` imports into +// pure-data/pure-logic modules that never touch them, which a browser +// bundler can't resolve (adcp#2364). // // Runs pre-transform via `onLoad` — prepending to the TS source rather than // the emitted JS — so esbuild's own sourcemap generation accounts for the // added lines, matching what the (removed) `banner` option got for free. // Detection uses a throwaway `transformSync` of the file (comments and types // stripped) instead of matching the raw source, so a comment that merely -// mentions "require()" can't trigger a false positive. +// mentions "require()" can't trigger a false positive. `require(` is only +// matched with a following quote, so a same-named class method (e.g. +// `async require(...features)`) doesn't also false-positive. function conditionalNodeShimPlugin() { const banner = [ "import { fileURLToPath as __adcpFileURLToPath } from 'node:url';", "import { dirname as __adcpDirname } from 'node:path';", "import { createRequire as __adcpCreateRequire } from 'node:module';", - 'const __filename = __adcpFileURLToPath(import.meta.url);', - 'const __dirname = __adcpDirname(__filename);', + 'const __dirname = __adcpDirname(__adcpFileURLToPath(import.meta.url));', 'const require = __adcpCreateRequire(import.meta.url);', ].join('\n'); - const needsShim = /\b(__dirname|__filename)\b|\brequire\s*\(/; + const needsShim = /\b__dirname\b|\brequire\s*\(\s*['"`]/; return { name: 'conditional-node-shim', From 1e825cad928daab91bb68baeacb860ddb3471e5c Mon Sep 17 00:00:00 2001 From: Ben Miner Date: Mon, 20 Jul 2026 15:36:53 -0500 Subject: [PATCH 3/3] refactor(schemas): consolidate __dirname-relative schema/data root resolution Replace the hand-tuned `path.join(__dirname, '..', ...)` arithmetic duplicated across 7 schema/data loaders with shared getPackageRoot()/ getSchemaDataRoots() helpers anchored via require.resolve self-reference, independent of each file's own directory depth. No public API changes. Part of ENG-130. --- .changeset/schema-data-root-consolidation.md | 5 + src/lib/conformance/schemaLoader.ts | 6 +- src/lib/internal/package-root.ts | 82 ++++++++++++++ src/lib/internal/schema-data-roots.ts | 17 +++ src/lib/server/error-arm-tools.ts | 6 +- src/lib/testing/storyboard/compliance.ts | 8 +- src/lib/v2/projection/canonical-properties.ts | 6 +- src/lib/v2/projection/catalog.ts | 16 +-- src/lib/v2/projection/registry.ts | 8 +- src/lib/validation/schema-loader.ts | 8 +- test/lib/package-root.test.js | 101 ++++++++++++++++++ test/lib/schema-data-roots.test.js | 23 ++++ test/lib/schema-loader-per-version.test.js | 3 + test/lib/v2-projection-loader-paths.test.js | 8 +- tsup.config.ts | 12 ++- 15 files changed, 271 insertions(+), 38 deletions(-) create mode 100644 .changeset/schema-data-root-consolidation.md create mode 100644 src/lib/internal/package-root.ts create mode 100644 src/lib/internal/schema-data-roots.ts create mode 100644 test/lib/package-root.test.js create mode 100644 test/lib/schema-data-roots.test.js diff --git a/.changeset/schema-data-root-consolidation.md b/.changeset/schema-data-root-consolidation.md new file mode 100644 index 000000000..5987d2c8f --- /dev/null +++ b/.changeset/schema-data-root-consolidation.md @@ -0,0 +1,5 @@ +--- +"@adcp/sdk": patch +--- + +Internal: consolidated the duplicated `__dirname`-relative schema/data-root resolution across 7 loaders (`validation/schema-loader.ts`, `conformance/schemaLoader.ts`, `server/error-arm-tools.ts`, `v2/projection/{catalog,registry,canonical-properties}.ts`, `testing/storyboard/compliance.ts`) into shared `getPackageRoot()`/`getSchemaDataRoots()` helpers (`src/lib/internal/`). Resolution now anchors via `require.resolve('@adcp/sdk/package.json')` self-reference instead of hand-tuned `path.join(__dirname, '..', ...)` arithmetic tied to each file's own directory depth. No public API changes. diff --git a/src/lib/conformance/schemaLoader.ts b/src/lib/conformance/schemaLoader.ts index 04448b173..74e88af66 100644 --- a/src/lib/conformance/schemaLoader.ts +++ b/src/lib/conformance/schemaLoader.ts @@ -3,6 +3,7 @@ import * as path from 'path'; import type { ConformanceToolName } from './types'; import { ADCP_VERSION } from '../version'; import { resolveBundleKey } from '../validation/schema-loader'; +import { getSchemaDataRoots } from '../internal/schema-data-roots'; type JsonSchema = Record; @@ -70,10 +71,11 @@ function findBundledDir(options: ConformanceSchemaOptions = {}): string { const version = options.version ?? ADCP_VERSION; const bundleKey = resolveBundleKey(version); - const distCandidate = path.resolve(__dirname, '..', 'schemas-data', bundleKey, 'bundled'); + const { builtSchemasDataRoot, sourceSchemasCacheRoot } = getSchemaDataRoots(); + const distCandidate = path.join(builtSchemasDataRoot, bundleKey, 'bundled'); if (fs.existsSync(distCandidate)) return distCandidate; - const srcCandidate = path.resolve(__dirname, '..', '..', '..', 'schemas', 'cache', version, 'bundled'); + const srcCandidate = path.join(sourceSchemasCacheRoot, version, 'bundled'); if (fs.existsSync(srcCandidate)) return srcCandidate; throw new Error( diff --git a/src/lib/internal/package-root.ts b/src/lib/internal/package-root.ts new file mode 100644 index 000000000..6a9b40ee1 --- /dev/null +++ b/src/lib/internal/package-root.ts @@ -0,0 +1,82 @@ +/** + * Resolve the @adcp/sdk package root — the directory containing this + * package's own `package.json` — independent of the calling module's own + * directory depth or bundling shape. + * + * Replaces the per-file `__dirname` arithmetic that used to be hand-tuned to + * each schema/data loader's own depth under `src/lib/` (one `..` for + * `validation/`, two for `v2/projection/`, four for `testing/storyboard/`), + * which silently breaks if any of those files ever moves. + */ + +import { existsSync, readFileSync } from 'fs'; +import path from 'path'; + +let cachedRoot: string | undefined; + +/** + * Primary: self-reference through this package's own `exports` map + * (`"./package.json": "./package.json"`). Node resolves `require(...)` calls + * (bare form, not `.resolve` chained) so tsup's conditional ESM shim still + * detects this file needs `require` injected under `.mjs` output. + */ +function resolveViaModuleResolution(): string | undefined { + try { + const pkg = require('@adcp/sdk/package.json') as { name?: string }; + if (pkg.name !== '@adcp/sdk') return undefined; + return path.dirname(require.resolve('@adcp/sdk/package.json')); + } catch { + return undefined; + } +} + +/** + * Fallback: walk up from a starting directory looking for an ancestor + * `package.json` whose `name` is `@adcp/sdk`. Covers environments where + * module self-resolution is unavailable (e.g. an aggressive downstream + * bundler that strips/rewrites `require.resolve`). + * + * Exported for direct testing; not part of the public API surface. + */ +export function _resolvePackageRootViaDirectoryWalk(start: string): string | undefined { + let dir = start; + for (;;) { + const candidate = path.join(dir, 'package.json'); + if (existsSync(candidate)) { + try { + const pkg = JSON.parse(readFileSync(candidate, 'utf-8')) as { name?: string }; + if (pkg.name === '@adcp/sdk') return dir; + } catch { + // Malformed/unrelated package.json — keep walking past it. + } + } + const parent = path.dirname(dir); + if (parent === dir) return undefined; + dir = parent; + } +} + +/** + * Resolve the package root, memoized after the first successful call. + * + * Throws if both resolution strategies fail — this indicates a broken + * install or an aggressive bundler that stripped `package.json`, not a + * recoverable runtime condition. + */ +export function getPackageRoot(): string { + if (cachedRoot) return cachedRoot; + const resolved = resolveViaModuleResolution() ?? _resolvePackageRootViaDirectoryWalk(__dirname); + if (!resolved) { + throw new Error( + '@adcp/sdk: could not resolve the package root (require.resolve self-reference and directory walk ' + + 'both failed). This indicates a broken install or an aggressive bundler that stripped package.json.' + ); + } + cachedRoot = resolved; + return cachedRoot; +} + +/** Test hook: clear the memoized package root. */ +export function _resetPackageRootCache(): void { + cachedRoot = undefined; +} diff --git a/src/lib/internal/schema-data-roots.ts b/src/lib/internal/schema-data-roots.ts new file mode 100644 index 000000000..de2cd8907 --- /dev/null +++ b/src/lib/internal/schema-data-roots.ts @@ -0,0 +1,17 @@ +import path from 'path'; +import { getPackageRoot } from './package-root'; + +export interface SchemaDataRoots { + /** dist/lib/schemas-data — populated by scripts/copy-schemas-to-dist.ts. Only exists post-build. */ + builtSchemasDataRoot: string; + /** schemas/cache — populated by scripts/sync-schemas.ts. Only exists in a source checkout. */ + sourceSchemasCacheRoot: string; +} + +export function getSchemaDataRoots(): SchemaDataRoots { + const root = getPackageRoot(); + return { + builtSchemasDataRoot: path.join(root, 'dist', 'lib', 'schemas-data'), + sourceSchemasCacheRoot: path.join(root, 'schemas', 'cache'), + }; +} diff --git a/src/lib/server/error-arm-tools.ts b/src/lib/server/error-arm-tools.ts index 90deb91a4..2ca79a6ea 100644 --- a/src/lib/server/error-arm-tools.ts +++ b/src/lib/server/error-arm-tools.ts @@ -26,6 +26,7 @@ import { readdirSync, readFileSync, existsSync } from 'fs'; import path from 'path'; import { ADCP_VERSION } from '../version'; import { resolveBundleKey } from '../validation/schema-loader'; +import { getSchemaDataRoots } from '../internal/schema-data-roots'; /** * Resolve the schema-cache root for a given AdCP version. @@ -43,12 +44,13 @@ import { resolveBundleKey } from '../validation/schema-loader'; */ function resolveBundledRoot(version: string): string | undefined { const key = resolveBundleKey(version); + const { builtSchemasDataRoot, sourceSchemasCacheRoot } = getSchemaDataRoots(); // Built layout (dist): dist/lib/schemas-data//bundled - const distCandidate = path.join(__dirname, '..', 'schemas-data', key, 'bundled'); + const distCandidate = path.join(builtSchemasDataRoot, key, 'bundled'); if (existsSync(distCandidate)) return distCandidate; // Source-tree layout (dev): schemas/cache//bundled - const cacheRoot = path.join(__dirname, '..', '..', '..', 'schemas', 'cache'); + const cacheRoot = sourceSchemasCacheRoot; const exactCandidate = path.join(cacheRoot, version, 'bundled'); if (existsSync(exactCandidate)) return exactCandidate; diff --git a/src/lib/testing/storyboard/compliance.ts b/src/lib/testing/storyboard/compliance.ts index ab8d2e27d..1bd8ef7f4 100644 --- a/src/lib/testing/storyboard/compliance.ts +++ b/src/lib/testing/storyboard/compliance.ts @@ -16,6 +16,7 @@ import { ADCPError } from '../../errors'; import { isAdcpVersionSupported } from '../../utils/adcp-version-config'; import { hasSchemaBundle, resolveBundleKey } from '../../validation/schema-loader'; import { synthesizeRequestSigningSteps } from './request-signing/synthesize'; +import { getPackageRoot } from '../../internal/package-root'; import type { RunnerSelectionResult, Storyboard } from './types'; /** @@ -207,11 +208,6 @@ export interface ResolvedStoryboards { not_applicable: NotApplicableStoryboard[]; } -function getRepoRoot(): string { - // Walks from src/lib/testing/storyboard/ (or dist/lib/testing/storyboard/) → package root. - return resolve(__dirname, '..', '..', '..', '..'); -} - /** * Resolve the compliance cache directory. * @@ -224,7 +220,7 @@ export function getComplianceCacheDir(options: ResolveOptions = {}): string { const configured = getConfiguredComplianceDir(options); if (configured) return configured; const version = options.version || readAdcpVersion(); - return join(getRepoRoot(), 'compliance', 'cache', version); + return join(getPackageRoot(), 'compliance', 'cache', version); } function readAdcpVersion(): string { diff --git a/src/lib/v2/projection/canonical-properties.ts b/src/lib/v2/projection/canonical-properties.ts index 70d13529c..ed5244ade 100644 --- a/src/lib/v2/projection/canonical-properties.ts +++ b/src/lib/v2/projection/canonical-properties.ts @@ -22,6 +22,7 @@ import { readFileSync, existsSync } from 'fs'; import path from 'path'; import type { CanonicalFormatKind } from './types'; import { BETA_VERSIONS_TO_TRY } from './cache-versions'; +import { getSchemaDataRoots } from '../../internal/schema-data-roots'; interface CanonicalSchema { properties?: { @@ -55,9 +56,10 @@ function findCacheRoot(): string { // is intentionally not copied — adopters pinned to 3.0.x GA hit the // throw below rather than silently picking up a v3.0 cache that // lacks canonical-format schemas). + const { builtSchemasDataRoot, sourceSchemasCacheRoot } = getSchemaDataRoots(); const candidates = [ - ...BETA_VERSIONS_TO_TRY.map(v => path.join(__dirname, '..', '..', 'schemas-data', v)), - ...BETA_VERSIONS_TO_TRY.map(v => path.join(__dirname, '..', '..', '..', '..', 'schemas', 'cache', v)), + ...BETA_VERSIONS_TO_TRY.map(v => path.join(builtSchemasDataRoot, v)), + ...BETA_VERSIONS_TO_TRY.map(v => path.join(sourceSchemasCacheRoot, v)), ]; for (const c of candidates) { if (existsSync(c)) return c; diff --git a/src/lib/v2/projection/catalog.ts b/src/lib/v2/projection/catalog.ts index 458e6ce0e..ac10e3571 100644 --- a/src/lib/v2/projection/catalog.ts +++ b/src/lib/v2/projection/catalog.ts @@ -22,6 +22,7 @@ import { readFileSync, existsSync } from 'fs'; import path from 'path'; import type { CanonicalFormatKind, V1FormatId } from './types'; +import { getPackageRoot } from '../../internal/package-root'; /** * Canonical projection reference (`canonical-projection-ref.json` in the @@ -120,21 +121,12 @@ function indexKey(agentUrl: string, id: string): string { export function loadCatalog(explicitPath?: string): CatalogIndex { if (cached) return cached; + const packageRoot = getPackageRoot(); const candidates = explicitPath ? [explicitPath] : [ - path.join(__dirname, 'aao-reference-formats.json'), - path.join( - __dirname, - '..', - '..', - '..', - '..', - 'test', - 'lib', - 'v2-projection-fixtures', - 'aao-reference-formats.json' - ), + path.join(packageRoot, 'dist', 'lib', 'v2', 'projection', 'aao-reference-formats.json'), + path.join(packageRoot, 'test', 'lib', 'v2-projection-fixtures', 'aao-reference-formats.json'), ]; for (const file of candidates) { diff --git a/src/lib/v2/projection/registry.ts b/src/lib/v2/projection/registry.ts index b84b20b06..083d774f6 100644 --- a/src/lib/v2/projection/registry.ts +++ b/src/lib/v2/projection/registry.ts @@ -30,6 +30,7 @@ import path from 'path'; import type { CanonicalFormatKind, V1FormatId } from './types'; import { AAO_CANONICAL_AGENT_URL } from './constants'; import { BETA_VERSIONS_TO_TRY } from './cache-versions'; +import { getSchemaDataRoots } from '../../internal/schema-data-roots'; interface RegistryEntryV1Pattern { format_id_glob?: string; @@ -78,14 +79,13 @@ let cached: CanonicalMappingRegistry | null = null; */ export function loadRegistry(cacheRoot?: string): CanonicalMappingRegistry { if (cached) return cached; + const { builtSchemasDataRoot, sourceSchemasCacheRoot } = getSchemaDataRoots(); const candidates = cacheRoot ? [path.join(cacheRoot, 'registries', 'v1-canonical-mapping.json')] : [ + ...BETA_VERSIONS_TO_TRY.map(v => path.join(builtSchemasDataRoot, v, 'registries', 'v1-canonical-mapping.json')), ...BETA_VERSIONS_TO_TRY.map(v => - path.join(__dirname, '..', '..', 'schemas-data', v, 'registries', 'v1-canonical-mapping.json') - ), - ...BETA_VERSIONS_TO_TRY.map(v => - path.join(__dirname, '..', '..', '..', '..', 'schemas', 'cache', v, 'registries', 'v1-canonical-mapping.json') + path.join(sourceSchemasCacheRoot, v, 'registries', 'v1-canonical-mapping.json') ), ]; for (const file of candidates) { diff --git a/src/lib/validation/schema-loader.ts b/src/lib/validation/schema-loader.ts index f17deefe9..dbaa65b77 100644 --- a/src/lib/validation/schema-loader.ts +++ b/src/lib/validation/schema-loader.ts @@ -20,6 +20,7 @@ import { readdirSync, readFileSync, existsSync } from 'fs'; import path from 'path'; import { ADCP_VERSION } from '../version'; import { ConfigurationError } from '../errors'; +import { getSchemaDataRoots } from '../internal/schema-data-roots'; export type ResponseVariant = 'sync' | 'submitted' | 'working' | 'input-required'; export type Direction = 'request' | ResponseVariant; @@ -239,7 +240,8 @@ function resolveSchemaRoot(version: string): string { const externalRoot = externalSchemaRoots.get(key); if (externalRoot && existsSync(externalRoot)) return externalRoot; - const distCandidate = path.join(__dirname, '..', 'schemas-data', key); + const { builtSchemasDataRoot, sourceSchemasCacheRoot } = getSchemaDataRoots(); + const distCandidate = path.join(builtSchemasDataRoot, key); if (existsSync(distCandidate)) return distCandidate; // Published builds carry exact prerelease bundle directories @@ -247,14 +249,14 @@ function resolveSchemaRoot(version: string): string { // alias (`3.1-rc`). Resolve that alias before falling back to source cache. const releasePrecisionMatch = /^\d+\.\d+-/.test(key); if (releasePrecisionMatch) { - const distPrereleaseCandidate = findPrereleaseBundle(path.join(__dirname, '..', 'schemas-data'), key); + const distPrereleaseCandidate = findPrereleaseBundle(builtSchemasDataRoot, key); if (distPrereleaseCandidate) return distPrereleaseCandidate; } // Source-tree fallback: cache stays exact-version-named, so map the key // back to the highest-patch cache directory in the same minor for stable // pins. Prereleases need an exact match. - const cacheRoot = path.join(__dirname, '..', '..', '..', 'schemas', 'cache'); + const cacheRoot = sourceSchemasCacheRoot; const exactCandidate = path.join(cacheRoot, version); if (existsSync(exactCandidate)) return exactCandidate; diff --git a/test/lib/package-root.test.js b/test/lib/package-root.test.js new file mode 100644 index 000000000..0e764bb41 --- /dev/null +++ b/test/lib/package-root.test.js @@ -0,0 +1,101 @@ +// getPackageRoot() replaces the per-file `__dirname` arithmetic that used to be +// duplicated across 7 schema/data loaders (validation/schema-loader.ts, +// conformance/schemaLoader.ts, server/error-arm-tools.ts, +// v2/projection/{catalog,registry,canonical-properties}.ts, +// testing/storyboard/compliance.ts). It resolves the package root via +// `require.resolve('@adcp/sdk/package.json')` self-reference — independent of +// the calling module's own directory depth — falling back to a directory walk. + +const { test, describe, after } = require('node:test'); +const assert = require('node:assert'); +const fs = require('node:fs'); +const os = require('node:os'); +const path = require('node:path'); + +const REPO_ROOT = path.resolve(__dirname, '..', '..'); +const { + getPackageRoot, + _resetPackageRootCache, + _resolvePackageRootViaDirectoryWalk, +} = require('../../dist/lib/internal/package-root.js'); + +describe('getPackageRoot', () => { + test('resolves to the actual package root via self-reference', () => { + _resetPackageRootCache(); + const root = getPackageRoot(); + assert.strictEqual(root, REPO_ROOT); + }); + + test('resolved root contains a package.json named @adcp/sdk', () => { + _resetPackageRootCache(); + const root = getPackageRoot(); + const pkg = JSON.parse(fs.readFileSync(path.join(root, 'package.json'), 'utf-8')); + assert.strictEqual(pkg.name, '@adcp/sdk'); + }); + + test('memoizes across calls', () => { + _resetPackageRootCache(); + const first = getPackageRoot(); + const second = getPackageRoot(); + assert.strictEqual(first, second); + }); + + test('_resetPackageRootCache() forces recomputation without changing the result', () => { + const before = getPackageRoot(); + _resetPackageRootCache(); + const after = getPackageRoot(); + assert.strictEqual(before, after); + }); +}); + +describe('_resolvePackageRootViaDirectoryWalk (fallback path)', () => { + let tmpRoot; + + after(() => { + if (tmpRoot && fs.existsSync(tmpRoot)) { + fs.rmSync(tmpRoot, { recursive: true, force: true }); + } + }); + + test('finds an ancestor package.json named @adcp/sdk from a nested start dir', () => { + tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'adcp-package-root-walk-')); + fs.writeFileSync(path.join(tmpRoot, 'package.json'), JSON.stringify({ name: '@adcp/sdk' })); + const nested = path.join(tmpRoot, 'dist', 'lib', 'internal'); + fs.mkdirSync(nested, { recursive: true }); + + const found = _resolvePackageRootViaDirectoryWalk(nested); + assert.strictEqual(found, tmpRoot); + }); + + test('skips an ancestor package.json with a different name', () => { + tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'adcp-package-root-walk-')); + fs.writeFileSync(path.join(tmpRoot, 'package.json'), JSON.stringify({ name: 'some-other-package' })); + const nested = path.join(tmpRoot, 'a', 'b'); + fs.mkdirSync(nested, { recursive: true }); + + const found = _resolvePackageRootViaDirectoryWalk(nested); + assert.strictEqual(found, undefined); + }); + + test('returns undefined when no package.json exists in the ancestry up to the filesystem root', () => { + tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'adcp-package-root-walk-')); + const nested = path.join(tmpRoot, 'a', 'b'); + fs.mkdirSync(nested, { recursive: true }); + + const found = _resolvePackageRootViaDirectoryWalk(nested); + assert.strictEqual(found, undefined); + }); + + test('tolerates a malformed package.json in the ancestry and keeps walking up', () => { + tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'adcp-package-root-walk-')); + const middle = path.join(tmpRoot, 'middle'); + fs.mkdirSync(middle, { recursive: true }); + fs.writeFileSync(path.join(middle, 'package.json'), '{ not valid json'); + fs.writeFileSync(path.join(tmpRoot, 'package.json'), JSON.stringify({ name: '@adcp/sdk' })); + const nested = path.join(middle, 'nested'); + fs.mkdirSync(nested, { recursive: true }); + + const found = _resolvePackageRootViaDirectoryWalk(nested); + assert.strictEqual(found, tmpRoot); + }); +}); diff --git a/test/lib/schema-data-roots.test.js b/test/lib/schema-data-roots.test.js new file mode 100644 index 000000000..2ea46fe3f --- /dev/null +++ b/test/lib/schema-data-roots.test.js @@ -0,0 +1,23 @@ +// getSchemaDataRoots() gives the 7 schema/data loaders one shared anchor for +// the two directories they each used to locate via hand-tuned `__dirname` +// arithmetic: the built (dist) schemas-data tree and the source-tree +// schemas/cache tree. + +const { test, describe } = require('node:test'); +const assert = require('node:assert'); +const path = require('node:path'); + +const REPO_ROOT = path.resolve(__dirname, '..', '..'); +const { getSchemaDataRoots } = require('../../dist/lib/internal/schema-data-roots.js'); + +describe('getSchemaDataRoots', () => { + test('builtSchemasDataRoot points at dist/lib/schemas-data under the package root', () => { + const { builtSchemasDataRoot } = getSchemaDataRoots(); + assert.strictEqual(builtSchemasDataRoot, path.join(REPO_ROOT, 'dist', 'lib', 'schemas-data')); + }); + + test('sourceSchemasCacheRoot points at schemas/cache under the package root', () => { + const { sourceSchemasCacheRoot } = getSchemaDataRoots(); + assert.strictEqual(sourceSchemasCacheRoot, path.join(REPO_ROOT, 'schemas', 'cache')); + }); +}); diff --git a/test/lib/schema-loader-per-version.test.js b/test/lib/schema-loader-per-version.test.js index 01ba31b00..dcbad53c5 100644 --- a/test/lib/schema-loader-per-version.test.js +++ b/test/lib/schema-loader-per-version.test.js @@ -70,6 +70,9 @@ function runPrereleaseSortFixture() { const tempDist = path.join(tempRoot, 'dist'); fs.cpSync(path.join(REPO_ROOT, 'dist'), tempDist, { recursive: true }); fs.symlinkSync(path.join(REPO_ROOT, 'node_modules'), path.join(tempRoot, 'node_modules'), 'dir'); + // getPackageRoot()'s require.resolve self-reference needs an ancestor + // package.json named @adcp/sdk to find this package's own root. + fs.cpSync(path.join(REPO_ROOT, 'package.json'), path.join(tempRoot, 'package.json')); const tempSchemasData = path.join(tempDist, 'lib', 'schemas-data'); writeMinimalGetProductsBundle(path.join(tempSchemasData, PRERELEASE_SORT_OLD), PRERELEASE_SORT_OLD, 'old'); writeMinimalGetProductsBundle(path.join(tempSchemasData, PRERELEASE_SORT_NEW), PRERELEASE_SORT_NEW, 'new'); diff --git a/test/lib/v2-projection-loader-paths.test.js b/test/lib/v2-projection-loader-paths.test.js index ad8bda150..855d02a05 100644 --- a/test/lib/v2-projection-loader-paths.test.js +++ b/test/lib/v2-projection-loader-paths.test.js @@ -44,9 +44,13 @@ before(() => { } tmpRoot = fs.mkdtempSync(path.join(os.tmpdir(), 'adcp-projection-loader-paths-')); - // Mimic node_modules/@adcp/sdk/dist by copying only the dist tree. - // Intentionally do NOT copy schemas/cache — that's the bug we're guarding. + // Mimic node_modules/@adcp/sdk/ by copying the dist tree plus package.json + // (every real npm install ships package.json regardless of the "files" + // field — getPackageRoot()'s require.resolve self-reference needs it to + // find this package's own root). Intentionally do NOT copy schemas/cache + // — that's the bug we're guarding. fs.cpSync(SRC_DIST, path.join(tmpRoot, 'dist'), { recursive: true }); + fs.cpSync(path.join(REPO_ROOT, 'package.json'), path.join(tmpRoot, 'package.json')); }); after(() => { diff --git a/tsup.config.ts b/tsup.config.ts index df085b67c..8d717748e 100644 --- a/tsup.config.ts +++ b/tsup.config.ts @@ -85,14 +85,16 @@ function fixDynamicImportExtensions() { // Build the library as a tree-shakeable dual package. // // `bundle: false` transpiles each source module 1:1 (no bundling, no chunks), -// so the output mirrors the source tree exactly. That keeps three things +// so the output mirrors the source tree exactly. That keeps two things // correct with zero extra work: // 1. a consumer's bundler tree-shakes across the preserved module graph when -// it imports from a public entry (importing one symbol stays lean), +// it imports from a public entry (importing one symbol stays lean), and // 2. the CLI and internal tooling that deep-`require` dist paths still -// resolve, and -// 3. the `__dirname`-based schema-data lookups keep their original directory -// depth (each module stays at its own path). +// resolve. +// (Schema/data-root resolution no longer depends on this: the 7 loaders that +// used to hand-tune `__dirname` arithmetic to their own directory depth now +// anchor via `getPackageRoot()`, which resolves via module self-reference +// independent of where the calling module lives — see src/lib/internal/.) // // `fixImportsPlugin` (see tsup#1240) supplies what `bundle: false` leaves out: // it appends the correct extension to relative imports, rewrites directory