Vendor a Perspective build that applies depth on a config update

Rebuilt from fleetside72/perspective at apply-depth-on-config-update, which
carries the patch ui/vendor has been describing: ViewConfig::apply_update
applied ten fields and neither group_by_depth nor split_by_depth, so a depth
set through restore() was dropped before the engine saw it. The new
perspective-js wasm is 81 bytes larger than the old, which is about right
for two calls and a generic.

Four things went wrong getting here, all of them host tooling rather than
the patch, and the script's preflight now catches three:

- pnpm 12 rejects a repeated `--if-present`, which sh_perspective.mjs emits
  once per package in scope. The tree needs pnpm 10; it pins no
  packageManager, so `npm i -g pnpm` gets something too new.
- `pip install cmake` gives 4.x, which clears the existing >= 3.29.5 floor
  and then fails in the Arrow build, because CMake 4 dropped support for
  cmake_minimum_required < 3.5.
- The pack step used `npm pack`, which leaves these packages' mutual
  `workspace:^` dependencies as-is; npm install then refuses the tarball
  with `Unsupported URL Type "workspace:"`. Now `pnpm pack`, which rewrites
  them -- and which is evidently how the previous tarballs were made, since
  theirs read `^5.4.0`.
- postinstall:playwright runs `playwright install --with-deps`, which
  apt-installs system libraries and needs root. Removed on the build branch.

npm normalised the vendor paths in package.json from ./vendor to vendor;
same meaning, left alone.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
Paul Trowbridge 2026-09-17 10:47:09 -04:00
parent f5d0f6b2f6
commit 251692a3f9
9 changed files with 78 additions and 27 deletions

16
ui/package-lock.json generated
View File

@ -8,10 +8,10 @@
"name": "ui", "name": "ui",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"@perspective-dev/client": "file:./vendor/perspective-dev-client-5.4.0.tgz", "@perspective-dev/client": "file:vendor/perspective-dev-client-5.4.0.tgz",
"@perspective-dev/server": "file:./vendor/perspective-dev-server-5.4.0.tgz", "@perspective-dev/server": "file:vendor/perspective-dev-server-5.4.0.tgz",
"@perspective-dev/viewer": "file:./vendor/perspective-dev-viewer-5.4.0.tgz", "@perspective-dev/viewer": "file:vendor/perspective-dev-viewer-5.4.0.tgz",
"@perspective-dev/viewer-datagrid": "file:./vendor/perspective-dev-viewer-datagrid-5.4.0.tgz", "@perspective-dev/viewer-datagrid": "file:vendor/perspective-dev-viewer-datagrid-5.4.0.tgz",
"react": "^19.2.5", "react": "^19.2.5",
"react-dom": "^19.2.5" "react-dom": "^19.2.5"
}, },
@ -578,7 +578,7 @@
"node_modules/@perspective-dev/client": { "node_modules/@perspective-dev/client": {
"version": "5.4.0", "version": "5.4.0",
"resolved": "file:vendor/perspective-dev-client-5.4.0.tgz", "resolved": "file:vendor/perspective-dev-client-5.4.0.tgz",
"integrity": "sha512-l9xCJ0W42wm9fLlwhoU838KyTE131qQTS686uQb/VcsLs30kCVjkoermCCUs0YHCDwDTJhly1y9DfAZDbkg9Ng==", "integrity": "sha512-DOk5TM4+SpDW29w6wJoHtH6oZVSon9YZjkMfKap4Lmf8SLp2PYwec/LouetkMfg4CvveGJemG4domsl8XeNafA==",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@perspective-dev/server": "^5.4.0", "@perspective-dev/server": "^5.4.0",
@ -590,13 +590,13 @@
"node_modules/@perspective-dev/server": { "node_modules/@perspective-dev/server": {
"version": "5.4.0", "version": "5.4.0",
"resolved": "file:vendor/perspective-dev-server-5.4.0.tgz", "resolved": "file:vendor/perspective-dev-server-5.4.0.tgz",
"integrity": "sha512-iTseRJB6TL6D9xjaMKMhh2NEKMIi9JR881J+GyQflHIQXK43fDlsIWtByUAoyZzZ7uA9KNZJZicirvONxIpLuw==", "integrity": "sha512-Z5oGEOYqTHMGoMElYbrfJL3YCtoGrAX6+22+3KwrxWDDLB5OlOOdsctfeEAdGqVeJ1/WFhqZp0fWBPEn4vcXrQ==",
"license": "Apache-2.0" "license": "Apache-2.0"
}, },
"node_modules/@perspective-dev/viewer": { "node_modules/@perspective-dev/viewer": {
"version": "5.4.0", "version": "5.4.0",
"resolved": "file:vendor/perspective-dev-viewer-5.4.0.tgz", "resolved": "file:vendor/perspective-dev-viewer-5.4.0.tgz",
"integrity": "sha512-7D6jNn7tDZ3W84MsydplWAJbqqpXIz5OlsHx5YG4sHvJ5q8ngZQvP+oZdxLQXL4hIbaxpskMld1gJbGltpcvUw==", "integrity": "sha512-2y2xRb5k9BedpnRXcaweRYC2LiP/mblNqbFaRtpqNhnVmp+c3pwO6kx57oRuLhyzkcmNZUAzlqZvs1MJNDn50g==",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@perspective-dev/client": "^5.4.0", "@perspective-dev/client": "^5.4.0",
@ -607,7 +607,7 @@
"node_modules/@perspective-dev/viewer-datagrid": { "node_modules/@perspective-dev/viewer-datagrid": {
"version": "5.4.0", "version": "5.4.0",
"resolved": "file:vendor/perspective-dev-viewer-datagrid-5.4.0.tgz", "resolved": "file:vendor/perspective-dev-viewer-datagrid-5.4.0.tgz",
"integrity": "sha512-7ITOmrIh1ZpiQbUR/KmHYck1sLA4cpNgpVMI/qJjQc9k/uypkT1vJmKYxv4MKR24TmEkOouBLNYiO+ItFKs8vg==", "integrity": "sha512-ccJOioKVPAGp/lv7RGSP2rtYj0PfwkJrNZWFMRJkmdz+eAPiHViDZhIHudOuA/2DOmcz6LbD617XaPasTU0Uog==",
"license": "Apache-2.0", "license": "Apache-2.0",
"dependencies": { "dependencies": {
"@perspective-dev/client": "^5.4.0", "@perspective-dev/client": "^5.4.0",

View File

@ -10,10 +10,10 @@
"preview": "vite preview" "preview": "vite preview"
}, },
"dependencies": { "dependencies": {
"@perspective-dev/client": "file:./vendor/perspective-dev-client-5.4.0.tgz", "@perspective-dev/client": "file:vendor/perspective-dev-client-5.4.0.tgz",
"@perspective-dev/server": "file:./vendor/perspective-dev-server-5.4.0.tgz", "@perspective-dev/server": "file:vendor/perspective-dev-server-5.4.0.tgz",
"@perspective-dev/viewer": "file:./vendor/perspective-dev-viewer-5.4.0.tgz", "@perspective-dev/viewer": "file:vendor/perspective-dev-viewer-5.4.0.tgz",
"@perspective-dev/viewer-datagrid": "file:./vendor/perspective-dev-viewer-datagrid-5.4.0.tgz", "@perspective-dev/viewer-datagrid": "file:vendor/perspective-dev-viewer-datagrid-5.4.0.tgz",
"react": "^19.2.5", "react": "^19.2.5",
"react-dom": "^19.2.5" "react-dom": "^19.2.5"
}, },

View File

@ -1,7 +1,8 @@
Built from https://github.com/fleetside72/perspective Built from https://github.com/fleetside72/perspective
branch column-axis-expand-collapse branch apply-depth-on-config-update
commit 2e3901d652650a33eaf19c2ddf049f7e525ea95b commit 71d1a7508aa86d7e7224ad91e247afe4c201313d
based on v5.4.0 based on unknown
built 2026-09-14T02:40:11Z on r710.hptrow.me built 2026-09-17T14:34:21Z on usmidsap02
dirty 0 uncommitted file(s) in the source tree at build time
Regenerate with ui/vendor/rebuild-perspective.sh Regenerate with ui/vendor/rebuild-perspective.sh

43
ui/vendor/README.md vendored
View File

@ -49,10 +49,11 @@ the change — the patch is small and additive, and the engine work is already
theirs. When a release ships it, delete this directory and put normal version theirs. When a release ships it, delete this directory and put normal version
ranges back in `ui/package.json`. ranges back in `ui/package.json`.
## Pending patch: depth fields on a config update ## Applied: depth fields on a config update
`0001-apply-depth-fields-on-config-update.patch` is not in the vendored `0001-apply-depth-fields-on-config-update.patch` is **in** the vendored
tarballs yet. It fixes an upstream bug in tarballs as of the 2026-09-17 build, from branch
`apply-depth-on-config-update`. It fixes an upstream bug in
`rust/perspective-client/src/rust/config/view_config.rs`: `rust/perspective-client/src/rust/config/view_config.rs`:
`ViewConfig::apply_update` applies ten fields and **neither `group_by_depth` `ViewConfig::apply_update` applies ten fields and **neither `group_by_depth`
nor `split_by_depth` is among them**. So a depth can be set when a view is nor `split_by_depth` is among them**. So a depth can be set when a view is
@ -88,9 +89,33 @@ cd ui && npm install
`protoc` installed are unresolved generated protobuf modules, none of them in `protoc` installed are unresolved generated protobuf modules, none of them in
`view_config.rs`. `view_config.rs`.
Until the rebuild lands, `applyDepth()` in `Forecast.jsx` reads the config back `applyDepth()` in `Forecast.jsx` reads the config back after restoring it and
after restoring it and falls back to the imperative `view.set_depth()` when the falls back to the imperative `view.set_depth()` when the value did not stick.
value did not stick. That fallback loses the depth whenever the viewer rebuilds With the patched engine installed that fallback should no longer run; it is kept
its view; the declarative path does not, which is the point of the patch. The for now so an unpatched engine still works, and can be removed once the
check is cheap and self-clearing — once the engine honours the field, the declarative path is confirmed.
fallback stops running on its own.
### Host tools this tree needs
The repo pins its Rust toolchain (`nightly-2026-06-01`), Emscripten (4.0.9) and
Binaryen (132) exactly, and pins **nothing** for the host tools — no
`packageManager`, no `.nvmrc`. So `npm i -g pnpm` and `pip install cmake` both
give versions this tree was not written against. The script's preflight now
rejects them, but for the record:
- **pnpm 10.x.** 11+ rejects a repeated `--if-present`, which
`sh_perspective.mjs:189` emits once per package in scope.
- **cmake 3.x**, not 4. Both satisfy the `>= 3.29.5` floor; CMake 4 removed
support for `cmake_minimum_required < 3.5`, which the C++ dependencies still
declare, and fails partway through the Arrow build.
- **protoc >= 22** (33.2 known good).
- **`pnpm pack`, not `npm pack`.** These packages depend on each other as
`workspace:^`, and only pnpm rewrites that to a concrete version. An
`npm pack` tarball is rejected at install: `Unsupported URL Type
"workspace:"`.
Two commits on the build branch are local build concessions rather than
fixes, and should be dropped before the real patch goes anywhere upstream:
removing the `postinstall:playwright` step (it runs `playwright install
--with-deps`, which apt-installs system libraries and so needs root), and
filling in the `allowBuilds` block pnpm 12 demanded.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -46,6 +46,18 @@ die() { echo -e "\033[0;31m ✗\033[0m $*" >&2; exit 1; }
Set PSP_DIR to use a different path." Set PSP_DIR to use a different path."
command -v pnpm >/dev/null || die "pnpm not found. Perspective builds with pnpm, not npm." command -v pnpm >/dev/null || die "pnpm not found. Perspective builds with pnpm, not npm."
# The repo pins its Rust toolchain, emsdk and Binaryen exactly, but pins nothing
# for the host tools -- no packageManager, no .nvmrc -- so `npm i -g pnpm` gets
# whatever is newest and that is not what this tree was written against. pnpm 11+
# rejects a repeated `--if-present`, which sh_perspective.mjs emits once per
# package in scope, and the build dies with:
# error: the argument '--if-present' cannot be used multiple times
pnpm_major=$(pnpm --version | cut -d. -f1)
if (( pnpm_major > 10 )); then
die "pnpm $(pnpm --version) is too new; this tree needs pnpm 10.x.
npm i -g pnpm@10"
fi
command -v protoc >/dev/null || die "protoc not found. command -v protoc >/dev/null || die "protoc not found.
Its VERSION selects which protobuf source tree the build clones, and a Its VERSION selects which protobuf source tree the build clones, and a
version below 22 pulls a layout the build cannot consume. Needs >= 22 version below 22 pulls a layout the build cannot consume. Needs >= 22
@ -55,7 +67,16 @@ cmake_ver=$(cmake --version 2>/dev/null | head -1 | grep -oE '[0-9]+\.[0-9]+(\.[
cmake_major=${cmake_ver%%.*}; cmake_minor=$(echo "$cmake_ver" | cut -d. -f2) cmake_major=${cmake_ver%%.*}; cmake_minor=$(echo "$cmake_ver" | cut -d. -f2)
if (( cmake_major < 3 || (cmake_major == 3 && cmake_minor < 29) )); then if (( cmake_major < 3 || (cmake_major == 3 && cmake_minor < 29) )); then
die "cmake $cmake_ver is too old; Perspective needs >= 3.29.5. die "cmake $cmake_ver is too old; Perspective needs >= 3.29.5.
A user-level install works: pip3 install --user 'cmake>=3.29.5'" A user-level install works: pip3 install --user 'cmake==3.31.*'"
fi
# And not too new: CMake 4 dropped compatibility with cmake_minimum_required
# below 3.5, which Perspective's C++ dependencies still declare. `pip install
# cmake` gives 4.x by default, which satisfies the floor above and then fails
# in the middle of the Arrow build.
if (( cmake_major >= 4 )); then
die "cmake $cmake_ver is too new; CMake 4 removed support for
cmake_minimum_required < 3.5, which the C++ dependencies still use.
pip3 install --user 'cmake==3.31.*'"
fi fi
info "Perspective checkout: $PSP" info "Perspective checkout: $PSP"
@ -73,10 +94,14 @@ info "Building (this takes ~40 minutes cold, a few minutes warm)…"
ok "build complete" ok "build complete"
# -- pack ------------------------------------------------------------------- # -- pack -------------------------------------------------------------------
# pnpm pack, not npm pack. These packages depend on each other as
# `workspace:^`, and only pnpm rewrites that to the concrete version on pack.
# npm leaves it, and npm install then refuses the tarball outright:
# npm error Unsupported URL Type "workspace:": workspace:^
info "Packing tarballs into $VENDOR" info "Packing tarballs into $VENDOR"
rm -f "$VENDOR"/*.tgz rm -f "$VENDOR"/*.tgz
for p in "${PACKAGES[@]}"; do for p in "${PACKAGES[@]}"; do
( cd "$PSP/$p" && npm pack --pack-destination "$VENDOR" >/dev/null ) ( cd "$PSP/$p" && pnpm pack --pack-destination "$VENDOR" >/dev/null )
ok "$(basename "$p")" ok "$(basename "$p")"
done done