Repository navigation
Control station/export frontend kit - #669
Draft
JavierRibaldelRio wants to merge 12 commits into
Draft
JavierRibaldelRio wants to merge 12 commits into
JavierRibaldelRio wants to merge 12 commits into
Conversation
globals.css declared @source globs reaching into testing-view and competition-view by relative path. Those paths resolve through the @workspace/ui symlink and every app importing globals.css inherited both views' classes, whether or not it was one of them. Each app now declares its own @source glob, matching the pattern already used by adj-view, logging-view and competition-view. Adds the missing one to testing-view and drops the per-app globs plus a dead commented-out line from the kit. testing-view CSS drops from 127.93 kB to 117.15 kB (148 selectors). Verified every removed class is unused in testing-view and the kit, and that all five apps still build.
The frontend-kit packages are about to emit dist/ directories. Without this, every git status would list them as untracked.
The socket layer hardcoded ws://127.0.0.1:${port}/backend and the set
of logger modules was a closed union of this repo's view names. Neither
works for a frontend living outside this repository.
- Add SocketConfig { url, host, port, path, secure, heartbeatIntervalMs }.
connect() still accepts a bare port, and with no config at all it
resolves to ws://127.0.0.1:4000/backend, so the five apps behave
exactly as before. Adds configure()/configureSocket() to set the
defaults once at boot, and resolveSocketUrl() plus a url getter for
diagnostics.
- Fix a dead reconnect: connect() returns early while a socket is open
and cleanup() was private, so useWebSocket's reconnect did nothing
whenever it was actually needed. Adds a public disconnect() and a
reconnect() that closes before reopening.
- Widen LoggerModule to accept any string while keeping autocomplete
for the known ones, export createLogger, add registerLoggerColor and
an ansi map, and ship colors for all five views. Existing logger.*
call sites are untouched.
- Honour heartbeatIntervalMs, where 0 disables the heartbeat.
- Export loggerColors from the package index, which it never was.
40 imports inside the kit referenced the package by its own name (@workspace/ui/lib/utils and friends). Self-reference resolution is supported unevenly across bundlers and, once the kit is published, it risks a consumer ending up with two instances of cn. One file already used a relative path, so this makes the kit internally consistent. Also drops the now-dead paths block from the kit's tsconfig, so a mistyped import fails loudly instead of resolving through the alias. All five apps build and their CSS output hashes are unchanged.
…ckage A new frontend will live outside this repository and needs the kit. That requires publishing it, and publishing requires a real npm scope: @workspace is the Turborepo template placeholder, not an organisation. - Merge @workspace/core into @workspace/ui as src/core/, exposed as the ./core subpath. One package means one version, one build and no internal workspace: dependency to coordinate when publishing. The React-free boundary the kit README describes survives as a folder. - Rename the directory ui -> kit, since it no longer holds only UI, and fix the esling-config -> eslint-config typo. - Rename @workspace/* to @hyperloop-upv/* across 183 files. - Drop the kit alias from the five app tsconfigs. Those paths pointed into the kit's source tree by relative path, which is exactly what does not exist for an external consumer. They were already inert: they live in a solution-style config with files: [], and the tsconfig.app.json that actually compiles src has no paths at all, so the apps already resolve the kit through its exports map. eslint-config and typescript-config stay private: publishing the former would force its 13 plugins into consumers' production dependencies. All five apps build with byte-identical CSS output, lint reports no new problems, and both .claude worktrees are untouched.
Publishing needs compiled output: an external consumer gets .tsx inside node_modules, and @vitejs/plugin-react-swc does not transform files there. Builds with Vite in library mode using Rollup's preserveModules, which mirrors src/ into dist/ so the wildcard subpath exports keep resolving as components are added, with no entry list to maintain. Chose Rollup over tsc and tsup because neither rewrites relative specifiers: both would emit extensionless imports, which is invalid ESM and only works because Vite retries extensions. Verified the output imports ../../lib/utils.js, with the extension. - exports still point at src/, so the five apps keep today's HMR straight into kit source. publishConfig.exports points at dist/ and is what a consumer sees. This requires pnpm publish: npm ignores the override and would ship a package pointing at .tsx. - Ship src/ alongside dist/ so the published globals.css keeps its own @source glob working against the package's own sources. No build-time CSS transform and no generated second stylesheet. - react, react-dom, lucide-react, tailwindcss and tw-animate-css become peers. Two copies of React break hooks, and LucideIcon leaks into the public props of SegmentedControl. - Drop the preinstall guard, which npm and yarn would run from inside a dependency and abort the consumer's install on. - Drop next-themes, zod and zustand: unused since the store was emptied. - Re-inject the 18 "use client" directives, which Rollup strips from the emitted JS. - Enforce the React-free boundary of src/core with a lint rule instead of only documenting it in the README. All five apps build with unchanged CSS output; tarball asserted for private, preinstall, exports retargeting, peers and workspace: leakage.
The workspace tables still listed ui and core as two packages. Rewrites the kit README around the published package: where code goes and why src/core may not import React, the build and why Rollup rather than tsc or tsup, why the tarball ships src/, and a consumer recipe covering peers, index.css, the vite dedupe, the tsconfig, pointing the socket at a remote backend and registering a logger module. States that the registry is not set up yet and that a tarball from pnpm pack is the way to consume it meanwhile.
The install step passed --filter=ui --filter=core. pnpm filters by package name, and those were never the names: the packages were @workspace/ui and @workspace/core, now merged into @hyperloop-upv/frontend-kit. Both filters selected nothing. Uses --filter="./frontend/**" instead, matching the build and test steps in the same job, so the install cannot drift from the package names again.
Adds the registry scope mapping and a manual publish workflow, so the
kit can reach a frontend living in another repository.
The root .npmrc carries no auth token on purpose. Every @hyperloop-upv/*
dependency here is a workspace link, so pnpm never contacts the
registry and nobody needs a token to install; a committed
_authToken=${NODE_AUTH_TOKEN} would break pnpm install for anyone
without that variable. Verified that a frozen-lockfile install still
succeeds with no token present.
The workflow is workflow_dispatch only and defaults to dry-run, so its
first ever run cannot publish by accident, and the publish step is
gated on an explicit boolean false so it fails closed. Before the
irreversible step it checks the dispatched version against the
committed one and asserts the tarball: private, the preinstall hook,
publishConfig.exports actually being applied, the ./core subpath, the
peers, a leaked workspace: range, and that src/ ships so Tailwind can
scan the kit inside node_modules.
Publishing uses pnpm, not npm: npm ignores publishConfig.exports and
would ship a package whose exports point at .tsx, with no error.
Both scripted steps were extracted from the YAML and run locally
against the real tarball.
The README still said the registry was not set up. Documents the consumer .npmrc, the classic PAT with read:packages that GitHub Packages requires even to download a public package, the CI permissions, and the release steps with the warning that a published version can never be reused.
Every Control Station release now publishes the kit at the same version, so v11.3.2 of the station and @hyperloop-upv/frontend-kit@11.3.2 refer to the same commit. The publish workflow gains a workflow_call trigger and release.yaml calls it as its last job, gated on the whole release having succeeded: publishing cannot be undone and must not happen for a release that failed to build. A publish-kit input, on by default, opts out. The version is injected in CI with pnpm version --no-git-tag-version rather than read from the committed package.json, which is the convention electron-app already follows; the kit's version becomes the same 0.0.0 placeholder, and the git tag is the record of what shipped. Prereleases get the next dist-tag instead of latest. The repo has shipped 11.3.2-beta-2 and 11.3.2-1, and publishing either as latest would make a prerelease the default install for every consumer. The dist-tag derivation and the version guard were both extracted from the YAML and run locally across the version formats this repo uses, including a leading v and the empty case.
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.