diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2c4e918..cccc8e2 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,6 +24,13 @@ jobs: - name: Build JavaScript run: yarn build:js + # The package.json each build/ directory holds is what npm receives: + # every entry point must name a file that is there, with no ./build/ or + # ./cjs/cjs/ paths and no string spread into exports (what broke the + # January 2026 releases and 7.5.19). + - name: Check built manifests + run: python3 scripts/check-built-manifests.py . wasm-util wasm-bridge wasm-crypto-asmjs wasm-crypto-wasm wasm-crypto-init wasm-crypto + - name: Lint run: yarn lint diff --git a/packages/wasm-bridge/package.json b/packages/wasm-bridge/package.json index 14c97be..34b63ab 100644 --- a/packages/wasm-bridge/package.json +++ b/packages/wasm-bridge/package.json @@ -14,145 +14,12 @@ "url": "https://git.pezkuwichain.io/pezkuwichain/pezkuwi-wasm.git" }, "sideEffects": [ - "./build/packageDetect.js", - "./build/cjs/packageDetect.js" + "./packageDetect.js", + "./packageDetect.cjs" ], "type": "module", - "types": "./build/index.d.ts", "version": "7.5.19", - "main": "./build/cjs/index.js", - "module": "./build/index.js", - "exports": { - ".": { - "module": { - "types": "./build/index.d.ts", - "default": "./build/index.js" - }, - "require": { - "types": "./build/cjs/index.d.ts", - "default": "./build/cjs/index.js" - }, - "default": { - "types": "./build/index.d.ts", - "default": "./build/index.js" - } - }, - "./bridge": { - "module": { - "types": "./build/bridge.d.ts", - "default": "./build/bridge.js" - }, - "require": { - "types": "./build/cjs/bridge.d.ts", - "default": "./build/cjs/bridge.js" - }, - "default": { - "types": "./build/bridge.d.ts", - "default": "./build/bridge.js" - } - }, - "./bundle": { - "module": { - "types": "./build/bundle.d.ts", - "default": "./build/bundle.js" - }, - "require": { - "types": "./build/cjs/bundle.d.ts", - "default": "./build/cjs/bundle.js" - }, - "default": { - "types": "./build/bundle.d.ts", - "default": "./build/bundle.js" - } - }, - "./cjs/*": "./build/cjs/*.js", - "./cjs/package.json": "./build/cjs/package.json", - "./init": { - "module": { - "types": "./build/init.d.ts", - "default": "./build/init.js" - }, - "require": { - "types": "./build/cjs/init.d.ts", - "default": "./build/cjs/init.js" - }, - "default": { - "types": "./build/init.d.ts", - "default": "./build/init.js" - } - }, - "./package.json": "./package.json", - "./packageDetect": { - "module": { - "types": "./build/packageDetect.d.ts", - "default": "./build/packageDetect.js" - }, - "require": { - "types": "./build/cjs/packageDetect.d.ts", - "default": "./build/cjs/packageDetect.js" - }, - "default": { - "types": "./build/packageDetect.d.ts", - "default": "./build/packageDetect.js" - } - }, - "./packageInfo": { - "module": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - }, - "require": { - "types": "./build/cjs/packageInfo.d.ts", - "default": "./build/cjs/packageInfo.js" - }, - "default": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - } - }, - "./packageInfo.js": { - "module": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - }, - "require": { - "types": "./build/cjs/packageInfo.d.ts", - "default": "./build/cjs/packageInfo.js" - }, - "default": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - } - }, - "./types": { - "module": { - "types": "./build/types.d.ts", - "default": "./build/types.js" - }, - "require": { - "types": "./build/cjs/types.d.ts", - "default": "./build/cjs/types.js" - }, - "default": { - "types": "./build/types.d.ts", - "default": "./build/types.js" - } - }, - "./wbg": { - "module": { - "types": "./build/wbg.d.ts", - "default": "./build/wbg.js" - }, - "require": { - "types": "./build/cjs/wbg.d.ts", - "default": "./build/cjs/wbg.js" - }, - "default": { - "types": "./build/wbg.d.ts", - "default": "./build/wbg.js" - } - } - }, + "main": "index.js", "dependencies": { "@pezkuwi/wasm-util": "7.5.19", "tslib": "^2.7.0" diff --git a/packages/wasm-crypto-asmjs/package.json b/packages/wasm-crypto-asmjs/package.json index 13b26eb..4c20906 100644 --- a/packages/wasm-crypto-asmjs/package.json +++ b/packages/wasm-crypto-asmjs/package.json @@ -14,89 +14,12 @@ "url": "https://git.pezkuwichain.io/pezkuwichain/pezkuwi-wasm.git" }, "sideEffects": [ - "./build/packageDetect.js", - "./build/cjs/packageDetect.js" + "./packageDetect.js", + "./packageDetect.cjs" ], "type": "module", - "types": "./build/index.d.ts", "version": "7.5.19", - "main": "./build/cjs/index.js", - "module": "./build/index.js", - "exports": { - ".": { - "module": { - "types": "./build/index.d.ts", - "default": "./build/index.js" - }, - "require": { - "types": "./build/cjs/index.d.ts", - "default": "./build/cjs/index.js" - }, - "default": { - "types": "./build/index.d.ts", - "default": "./build/index.js" - } - }, - "./bundle": { - "module": { - "types": "./build/bundle.d.ts", - "default": "./build/bundle.js" - }, - "require": { - "types": "./build/cjs/bundle.d.ts", - "default": "./build/cjs/bundle.js" - }, - "default": { - "types": "./build/bundle.d.ts", - "default": "./build/bundle.js" - } - }, - "./cjs/*": "./build/cjs/*.js", - "./cjs/package.json": "./build/cjs/package.json", - "./package.json": "./package.json", - "./packageDetect": { - "module": { - "types": "./build/packageDetect.d.ts", - "default": "./build/packageDetect.js" - }, - "require": { - "types": "./build/cjs/packageDetect.d.ts", - "default": "./build/cjs/packageDetect.js" - }, - "default": { - "types": "./build/packageDetect.d.ts", - "default": "./build/packageDetect.js" - } - }, - "./packageInfo": { - "module": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - }, - "require": { - "types": "./build/cjs/packageInfo.d.ts", - "default": "./build/cjs/packageInfo.js" - }, - "default": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - } - }, - "./packageInfo.js": { - "module": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - }, - "require": { - "types": "./build/cjs/packageInfo.d.ts", - "default": "./build/cjs/packageInfo.js" - }, - "default": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - } - } - }, + "main": "index.js", "dependencies": { "tslib": "^2.7.0" }, diff --git a/packages/wasm-crypto-init/package.json b/packages/wasm-crypto-init/package.json index 2f0f4a8..c3ae070 100644 --- a/packages/wasm-crypto-init/package.json +++ b/packages/wasm-crypto-init/package.json @@ -14,192 +14,14 @@ "url": "https://git.pezkuwichain.io/pezkuwichain/pezkuwi-wasm.git" }, "sideEffects": [ - "./build/packageDetect.js", - "./build/cjs/packageDetect.js" + "./packageDetect.js", + "./packageDetect.cjs" ], "type": "module", - "types": "./build/wasm.d.ts", "version": "7.5.19", - "browser": "./build/cjs/wasm.js", - "main": "./build/cjs/wasm.js", - "module": "./build/wasm.js", - "react-native": "./build/cjs/asm.js", - "exports": { - ".": { - "types": "./build/wasm.d.ts", - "react-native": { - "module": { - "types": "./build/asm.d.ts", - "default": "./build/asm.js" - }, - "require": { - "types": "./build/cjs/asm.d.ts", - "default": "./build/cjs/asm.js" - }, - "default": { - "types": "./build/asm.d.ts", - "default": "./build/asm.js" - } - }, - "browser": { - "module": { - "types": "./build/wasm.d.ts", - "default": "./build/wasm.js" - }, - "require": { - "types": "./build/cjs/wasm.d.ts", - "default": "./build/cjs/wasm.js" - }, - "default": { - "types": "./build/wasm.d.ts", - "default": "./build/wasm.js" - } - }, - "node": { - "module": { - "types": "./build/wasm.d.ts", - "default": "./build/wasm.js" - }, - "require": { - "types": "./build/cjs/wasm.d.ts", - "default": "./build/cjs/wasm.js" - }, - "default": { - "types": "./build/wasm.d.ts", - "default": "./build/wasm.js" - } - } - }, - "./asm": { - "module": { - "types": "./build/asm.d.ts", - "default": "./build/asm.js" - }, - "require": { - "types": "./build/cjs/asm.d.ts", - "default": "./build/cjs/asm.js" - }, - "default": { - "types": "./build/asm.d.ts", - "default": "./build/asm.js" - } - }, - "./both": { - "module": { - "types": "./build/both.d.ts", - "default": "./build/both.js" - }, - "require": { - "types": "./build/cjs/both.d.ts", - "default": "./build/cjs/both.js" - }, - "default": { - "types": "./build/both.d.ts", - "default": "./build/both.js" - } - }, - "./bundle": { - "module": { - "types": "./build/bundle.d.ts", - "default": "./build/bundle.js" - }, - "require": { - "types": "./build/cjs/bundle.d.ts", - "default": "./build/cjs/bundle.js" - }, - "default": { - "types": "./build/bundle.d.ts", - "default": "./build/bundle.js" - } - }, - "./cjs/*": "./build/cjs/*.js", - "./cjs/package.json": "./build/cjs/package.json", - "./none": { - "module": { - "types": "./build/none.d.ts", - "default": "./build/none.js" - }, - "require": { - "types": "./build/cjs/none.d.ts", - "default": "./build/cjs/none.js" - }, - "default": { - "types": "./build/none.d.ts", - "default": "./build/none.js" - } - }, - "./package.json": "./package.json", - "./packageDetect": { - "module": { - "types": "./build/packageDetect.d.ts", - "default": "./build/packageDetect.js" - }, - "require": { - "types": "./build/cjs/packageDetect.d.ts", - "default": "./build/cjs/packageDetect.js" - }, - "default": { - "types": "./build/packageDetect.d.ts", - "default": "./build/packageDetect.js" - } - }, - "./packageInfo": { - "module": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - }, - "require": { - "types": "./build/cjs/packageInfo.d.ts", - "default": "./build/cjs/packageInfo.js" - }, - "default": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - } - }, - "./packageInfo.js": { - "module": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - }, - "require": { - "types": "./build/cjs/packageInfo.d.ts", - "default": "./build/cjs/packageInfo.js" - }, - "default": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - } - }, - "./types": { - "module": { - "types": "./build/types.d.ts", - "default": "./build/types.js" - }, - "require": { - "types": "./build/cjs/types.d.ts", - "default": "./build/cjs/types.js" - }, - "default": { - "types": "./build/types.d.ts", - "default": "./build/types.js" - } - }, - "./wasm": { - "module": { - "types": "./build/wasm.d.ts", - "default": "./build/wasm.js" - }, - "require": { - "types": "./build/cjs/wasm.d.ts", - "default": "./build/cjs/wasm.js" - }, - "default": { - "types": "./build/wasm.d.ts", - "default": "./build/wasm.js" - } - } - }, + "browser": "wasm.js", + "main": "wasm.js", + "react-native": "asm.js", "dependencies": { "@pezkuwi/wasm-bridge": "7.5.19", "@pezkuwi/wasm-crypto-asmjs": "7.5.19", diff --git a/packages/wasm-crypto-wasm/package.json b/packages/wasm-crypto-wasm/package.json index 2c6a27a..116a514 100644 --- a/packages/wasm-crypto-wasm/package.json +++ b/packages/wasm-crypto-wasm/package.json @@ -14,103 +14,12 @@ "url": "https://git.pezkuwichain.io/pezkuwichain/pezkuwi-wasm.git" }, "sideEffects": [ - "./build/packageDetect.js", - "./build/cjs/packageDetect.js" + "./packageDetect.js", + "./packageDetect.cjs" ], "type": "module", - "types": "./build/index.d.ts", "version": "7.5.19", - "main": "./build/cjs/index.js", - "module": "./build/index.js", - "exports": { - ".": { - "module": { - "types": "./build/index.d.ts", - "default": "./build/index.js" - }, - "require": { - "types": "./build/cjs/index.d.ts", - "default": "./build/cjs/index.js" - }, - "default": { - "types": "./build/index.d.ts", - "default": "./build/index.js" - } - }, - "./bundle": { - "module": { - "types": "./build/bundle.d.ts", - "default": "./build/bundle.js" - }, - "require": { - "types": "./build/cjs/bundle.d.ts", - "default": "./build/cjs/bundle.js" - }, - "default": { - "types": "./build/bundle.d.ts", - "default": "./build/bundle.js" - } - }, - "./bytes": { - "module": { - "types": "./build/bytes.d.ts", - "default": "./build/bytes.js" - }, - "require": { - "types": "./build/cjs/bytes.d.ts", - "default": "./build/cjs/bytes.js" - }, - "default": { - "types": "./build/bytes.d.ts", - "default": "./build/bytes.js" - } - }, - "./cjs/*": "./build/cjs/*.js", - "./cjs/package.json": "./build/cjs/package.json", - "./package.json": "./package.json", - "./packageDetect": { - "module": { - "types": "./build/packageDetect.d.ts", - "default": "./build/packageDetect.js" - }, - "require": { - "types": "./build/cjs/packageDetect.d.ts", - "default": "./build/cjs/packageDetect.js" - }, - "default": { - "types": "./build/packageDetect.d.ts", - "default": "./build/packageDetect.js" - } - }, - "./packageInfo": { - "module": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - }, - "require": { - "types": "./build/cjs/packageInfo.d.ts", - "default": "./build/cjs/packageInfo.js" - }, - "default": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - } - }, - "./packageInfo.js": { - "module": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - }, - "require": { - "types": "./build/cjs/packageInfo.d.ts", - "default": "./build/cjs/packageInfo.js" - }, - "default": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - } - } - }, + "main": "index.js", "dependencies": { "@pezkuwi/wasm-util": "7.5.19", "tslib": "^2.7.0" diff --git a/packages/wasm-crypto/package.json b/packages/wasm-crypto/package.json index 3e7faca..515b667 100644 --- a/packages/wasm-crypto/package.json +++ b/packages/wasm-crypto/package.json @@ -14,167 +14,20 @@ "url": "https://git.pezkuwichain.io/pezkuwichain/pezkuwi-wasm.git" }, "sideEffects": [ - "./build/initNone.js", - "./build/cjs/initNone.js", - "./build/initOnlyAsm.js", - "./build/cjs/initOnlyAsm.js", - "./build/initOnlyWasm.js", - "./build/cjs/initOnlyWasm.js", - "./build/initWasmAsm.js", - "./build/cjs/initWasmAsm.js", - "./build/packageDetect.js", - "./build/cjs/packageDetect.js" + "./initNone.js", + "./initNone.cjs", + "./initOnlyAsm.js", + "./initOnlyAsm.cjs", + "./initOnlyWasm.js", + "./initOnlyWasm.cjs", + "./initWasmAsm.js", + "./initWasmAsm.cjs", + "./packageDetect.js", + "./packageDetect.cjs" ], "type": "module", - "types": "./build/index.d.ts", "version": "7.5.19", - "main": "./build/cjs/index.js", - "module": "./build/index.js", - "exports": { - ".": { - "module": { - "types": "./build/index.d.ts", - "default": "./build/index.js" - }, - "require": { - "types": "./build/cjs/index.d.ts", - "default": "./build/cjs/index.js" - }, - "default": { - "types": "./build/index.d.ts", - "default": "./build/index.js" - } - }, - "./bundle": { - "module": { - "types": "./build/bundle.d.ts", - "default": "./build/bundle.js" - }, - "require": { - "types": "./build/cjs/bundle.d.ts", - "default": "./build/cjs/bundle.js" - }, - "default": { - "types": "./build/bundle.d.ts", - "default": "./build/bundle.js" - } - }, - "./cjs/*": "./build/cjs/*.js", - "./cjs/package.json": "./build/cjs/package.json", - "./init": { - "module": { - "types": "./build/init.d.ts", - "default": "./build/init.js" - }, - "require": { - "types": "./build/cjs/init.d.ts", - "default": "./build/cjs/init.js" - }, - "default": { - "types": "./build/init.d.ts", - "default": "./build/init.js" - } - }, - "./initNone": { - "module": { - "types": "./build/initNone.d.ts", - "default": "./build/initNone.js" - }, - "require": { - "types": "./build/cjs/initNone.d.ts", - "default": "./build/cjs/initNone.js" - }, - "default": { - "types": "./build/initNone.d.ts", - "default": "./build/initNone.js" - } - }, - "./initOnlyAsm": { - "module": { - "types": "./build/initOnlyAsm.d.ts", - "default": "./build/initOnlyAsm.js" - }, - "require": { - "types": "./build/cjs/initOnlyAsm.d.ts", - "default": "./build/cjs/initOnlyAsm.js" - }, - "default": { - "types": "./build/initOnlyAsm.d.ts", - "default": "./build/initOnlyAsm.js" - } - }, - "./initOnlyWasm": { - "module": { - "types": "./build/initOnlyWasm.d.ts", - "default": "./build/initOnlyWasm.js" - }, - "require": { - "types": "./build/cjs/initOnlyWasm.d.ts", - "default": "./build/cjs/initOnlyWasm.js" - }, - "default": { - "types": "./build/initOnlyWasm.d.ts", - "default": "./build/initOnlyWasm.js" - } - }, - "./initWasmAsm": { - "module": { - "types": "./build/initWasmAsm.d.ts", - "default": "./build/initWasmAsm.js" - }, - "require": { - "types": "./build/cjs/initWasmAsm.d.ts", - "default": "./build/cjs/initWasmAsm.js" - }, - "default": { - "types": "./build/initWasmAsm.d.ts", - "default": "./build/initWasmAsm.js" - } - }, - "./package.json": "./package.json", - "./packageDetect": { - "module": { - "types": "./build/packageDetect.d.ts", - "default": "./build/packageDetect.js" - }, - "require": { - "types": "./build/cjs/packageDetect.d.ts", - "default": "./build/cjs/packageDetect.js" - }, - "default": { - "types": "./build/packageDetect.d.ts", - "default": "./build/packageDetect.js" - } - }, - "./packageInfo": { - "module": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - }, - "require": { - "types": "./build/cjs/packageInfo.d.ts", - "default": "./build/cjs/packageInfo.js" - }, - "default": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - } - }, - "./packageInfo.js": { - "module": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - }, - "require": { - "types": "./build/cjs/packageInfo.d.ts", - "default": "./build/cjs/packageInfo.js" - }, - "default": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - } - } - }, + "main": "index.js", "dependencies": { "@noble/hashes": "^1.3.3", "@pezkuwi/wasm-bridge": "7.5.19", diff --git a/packages/wasm-util/package.json b/packages/wasm-util/package.json index b6278d6..7aee062 100644 --- a/packages/wasm-util/package.json +++ b/packages/wasm-util/package.json @@ -14,117 +14,12 @@ "url": "https://git.pezkuwichain.io/pezkuwichain/pezkuwi-wasm.git" }, "sideEffects": [ - "./build/packageDetect.js", - "./build/cjs/packageDetect.js" + "./packageDetect.js", + "./packageDetect.cjs" ], "type": "module", - "types": "./build/index.d.ts", "version": "7.5.19", - "main": "./build/cjs/index.js", - "module": "./build/index.js", - "exports": { - ".": { - "module": { - "types": "./build/index.d.ts", - "default": "./build/index.js" - }, - "require": { - "types": "./build/cjs/index.d.ts", - "default": "./build/cjs/index.js" - }, - "default": { - "types": "./build/index.d.ts", - "default": "./build/index.js" - } - }, - "./base64": { - "module": { - "types": "./build/base64.d.ts", - "default": "./build/base64.js" - }, - "require": { - "types": "./build/cjs/base64.d.ts", - "default": "./build/cjs/base64.js" - }, - "default": { - "types": "./build/base64.d.ts", - "default": "./build/base64.js" - } - }, - "./bundle": { - "module": { - "types": "./build/bundle.d.ts", - "default": "./build/bundle.js" - }, - "require": { - "types": "./build/cjs/bundle.d.ts", - "default": "./build/cjs/bundle.js" - }, - "default": { - "types": "./build/bundle.d.ts", - "default": "./build/bundle.js" - } - }, - "./cjs/*": "./build/cjs/*.js", - "./cjs/package.json": "./build/cjs/package.json", - "./fflate": { - "module": { - "types": "./build/fflate.d.ts", - "default": "./build/fflate.js" - }, - "require": { - "types": "./build/cjs/fflate.d.ts", - "default": "./build/cjs/fflate.js" - }, - "default": { - "types": "./build/fflate.d.ts", - "default": "./build/fflate.js" - } - }, - "./package.json": "./package.json", - "./packageDetect": { - "module": { - "types": "./build/packageDetect.d.ts", - "default": "./build/packageDetect.js" - }, - "require": { - "types": "./build/cjs/packageDetect.d.ts", - "default": "./build/cjs/packageDetect.js" - }, - "default": { - "types": "./build/packageDetect.d.ts", - "default": "./build/packageDetect.js" - } - }, - "./packageInfo": { - "module": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - }, - "require": { - "types": "./build/cjs/packageInfo.d.ts", - "default": "./build/cjs/packageInfo.js" - }, - "default": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - } - }, - "./packageInfo.js": { - "module": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - }, - "require": { - "types": "./build/cjs/packageInfo.d.ts", - "default": "./build/cjs/packageInfo.js" - }, - "default": { - "types": "./build/packageInfo.d.ts", - "default": "./build/packageInfo.js" - } - } - }, + "main": "index.js", "dependencies": { "tslib": "^2.7.0" }, diff --git a/scripts/check-built-manifests.py b/scripts/check-built-manifests.py new file mode 100755 index 0000000..9b379de --- /dev/null +++ b/scripts/check-built-manifests.py @@ -0,0 +1,99 @@ +#!/usr/bin/env python3 +"""Check the package.json the build wrote into each packages/*/build directory. + +This is the manifest npm receives. It fails on what broke the January 2026 +releases and wasm 7.5.19: an entry point (main, module, types, browser, +react-native, every exports target) naming a file that is not in the build +directory, a path with ./build/ or a doubled ./cjs/cjs/ in it, numeric keys +inside exports (a string spread into an object), and workspace:/portal:/link: +dependency ranges. + + check-built-manifests.py [package ...] + +Prints one line per package and exits 1 if any package fails. +""" +import json +import pathlib +import sys + +ENTRY_FIELDS = ('main', 'module', 'types', 'typings', 'browser', 'react-native') +DEP_FIELDS = ('dependencies', 'peerDependencies', 'optionalDependencies') + + +def targets(node, path): + """Yield (json-path, target string) for every string leaf under exports.""" + if isinstance(node, str): + yield path, node + elif isinstance(node, dict): + for key, value in node.items(): + yield from targets(value, f'{path}/{key}') + elif isinstance(node, list): + for i, value in enumerate(node): + yield from targets(value, f'{path}[{i}]') + + +def numeric_keys(node, path): + if isinstance(node, dict): + for key, value in node.items(): + if key.isdigit(): + yield f'{path}/{key}' + yield from numeric_keys(value, f'{path}/{key}') + + +def check(build): + problems = [] + manifest = build / 'package.json' + if not manifest.is_file(): + return ['no build/package.json'] + pkg = json.loads(manifest.read_text()) + + def check_path(where, target): + if not isinstance(target, str) or not target.startswith('.'): + return + if '/build/' in target or target.startswith('./build') or '/cjs/cjs/' in target: + problems.append(f'{where}: suspicious path {target}') + if '*' in target: + base = build / target.split('*', 1)[0] + if not base.parent.exists(): + problems.append(f'{where}: {target} has no directory') + return + if not (build / target).is_file(): + problems.append(f'{where}: {target} does not exist') + + for field in ENTRY_FIELDS: + value = pkg.get(field) + if isinstance(value, str): + check_path(field, value) + for where, target in targets(pkg.get('exports'), 'exports'): + check_path(where, target) + for where in numeric_keys(pkg.get('exports'), 'exports'): + problems.append(f'{where}: numeric key (a string spread into an object)') + for field in DEP_FIELDS: + for dep, rng in (pkg.get(field) or {}).items(): + if str(rng).startswith(('workspace:', 'portal:', 'link:', 'file:')): + problems.append(f'{field}.{dep}: {rng}') + return problems + + +def main(): + repo = pathlib.Path(sys.argv[1]) + names = sys.argv[2:] + builds = [repo / 'packages' / n / 'build' for n in names] if names else sorted(repo.glob('packages/*/build')) + failed = 0 + for build in builds: + problems = check(build) + name = build.parent.name + if problems: + failed += 1 + print(f'FAIL {name}') + for p in problems[:12]: + print(f' {p}') + if len(problems) > 12: + print(f' ... {len(problems) - 12} more') + else: + print(f'ok {name}') + sys.exit(1 if failed else 0) + + +if __name__ == '__main__': + main()