5.5 KiB
sk-react-toolkit
The shared code of the web tools built as a Fastify server in TypeScript and a React application with MUI built by Vite, such as azure-platform's manage-ui and sql-query-webui. It is TypeScript source: Node 26 runs the server helpers, and the application's Vite build compiles the web code.
Using it
The package is @koszewscy/sk-react-toolkit, published to the npm registry of Gitea,
https://gitea.koszewscy.waw.pl/api/packages/koszewscy/npm/. An application imports it as
sk-react-toolkit, by an alias. Its .npmrc names the registry of the scope:
@koszewscy:registry=https://gitea.koszewscy.waw.pl/api/packages/koszewscy/npm/
{ "dependencies": { "sk-react-toolkit": "npm:@koszewscy/sk-react-toolkit@^0.1.0" } }
While the toolkit and an application change together, the application depends on the checkout next to its own repository instead, the TypeScript source:
{ "dependencies": { "sk-react-toolkit": "file:../sk-react-toolkit" } }
npm links the checkout into node_modules, and npm ci keeps the link. The web application adds
the toolkit's resolve options and font plugin to its vite.config.ts, so React, MUI and Emotion
come from its own node_modules, and allows the dev server to read the checkout:
import { font, fontChoice, TOOLKIT_RESOLVE } from 'sk-react-toolkit/vite'
import { defineConfig, loadEnv } from 'vite'
export default defineConfig(({ mode }) => ({
plugins: [react(), font(fontChoice(loadEnv(mode, import.meta.dirname)))],
resolve: TOOLKIT_RESOLVE,
server: { fs: { allow: ['..', '../../sk-react-toolkit'] } },
}))
The peer dependencies are the application's: fastify and @fastify/static for the server
helpers; react, react-dom, @mui/material, @mui/icons-material and Emotion for the web
code; vite for the Vite helpers.
sk-react-toolkit/server
| Export | Purpose |
|---|---|
HttpError |
an error answered with its status and { error }, with problems and a detail message for a refused write |
strict(properties) |
the JSON schema of an object with exactly these properties, all required |
errorHandler(log) |
Fastify's error handler: { error }, or { error, problems, message }; unexpected 5xx errors logged with their stack |
notFoundHandler(webDir, buildHint) |
404 for /api paths, index.html for the others, 503 with the hint while the frontend is not built |
createLog, timestampsOn, QUIET, Log |
the log of a server, with optional timestamps and requests; QUIET for tests |
fail(message) |
prints the error in red and ends the process with status 2 |
gitVersion(dir, variable) |
git describe of the checkout, else the environment variable, else dev |
exitOnSignals(close) |
closes the server on Ctrl-C and SIGTERM, ending the process after 5 seconds at most |
readJsonObject(path, options) |
a JSON object file and its version, the SHA-256 of its bytes; optionally {} for a missing file |
sk-react-toolkit/web
| Export | Purpose |
|---|---|
request, ApiError, Validation |
a JSON call to the backend, its error with the problems of a refused write, and the answer of a validate endpoint |
appTheme(colorSchemes?), renderApp(options) |
the theme (light, dark and system, Regular font, small text fields) and the startup that retries the first call while showing Connecting |
REGULAR, MONOSPACED, verbatim |
the font styles and the attributes of inputs the browser must not change |
Card |
a centered panel with a title and a message |
ThemeMenu |
the button cycling light, dark and system theme |
SwitcherMenu, SwitcherItem |
a button naming the item chosen, whose menu chooses another, such as a page or a connection |
TextInput |
a text field with clear and show/hide buttons |
RowDialog, useValidation |
a dialog that edits a value validated by the server as it changes, and the validation hook |
createBrowserSettings(keys, event) |
switches kept in localStorage and followed across tabs |
sk-react-toolkit/vite
| Export | Purpose |
|---|---|
font(choice), fontChoice(env), FONTS |
the font plugin of VITE_FONT: cdn (Google Fonts links, the default), bundled (@fontsource/roboto, a dependency of the application) or none |
TOOLKIT_RESOLVE |
the resolve options that keep one copy of React, MUI and Emotion |
Development
npm install installs the peer dependencies as development dependencies; npm run typecheck
and npm run lint check the code. npm run build (build.mjs) builds the published package in
dist/: the code compiled to JavaScript with its declarations, README.md, CHANGELOG.md and a
package.json whose exports name the compiled files.
Releases
./release.mjs commits, tags the version of the newest CHANGELOG.md entry and pushes main with
the tag; -n prints the git commands instead. The version of a release of the code, x.y.z, is
that of package.json, so a release raises both. A tag x.y.z-n releases changes that are not
code changes; its version is already published, so its run publishes nothing.
The Release workflow, .gitea/workflows/release.yml, builds and publishes the package on Gitea
Actions for each tag and on demand: it installs the dependencies, typechecks and lints the code,
builds the package and publishes dist/ to the npm registry of the owner CI_OWNER on the server
CI_URL, with CI_TOKEN, a token with the package scope; all three are secrets of the
repository. A version already published is skipped, as the registry refuses the same version
again.