mirror of
https://github.com/bookorbit/bookorbit.git
synced 2026-11-03 08:21:39 -06:00
2faa32c09d
A provider identifier parsed out of an OPF was passed on verbatim, so a Calibre `opf:scheme="AMAZON"` holding a product URL reached a varchar(20) column as a 36-character value. It could not be stored, and the next manual save of that book was rejected for a field the user never typed into. Drop an identifier that cannot fit its column rather than truncating it: an overflowing value is not a long identifier, it is a different kind of value, and its first 20 characters are not an ASIN either. Enforce the same bound where every extractor converges, so no parser can fail a metadata write with a Postgres 22001. Keep the server's description of a rejected save instead of discarding the response body. Only that text names the field at fault, so the editor showed a bare "HTTP 400" and left the reason in the network tab. It stays untranslated, so it is preferred over the catalog message rather than replacing it, and the failure is carried as a structured value so the component still translates everything else. Tie the DTO limits to the column widths they were copied from, and guard the pair with a test, since nothing connected them when they drifted apart. Stand Node's built-in web storage down in the client test run. Node 26 defines localStorage on globalThis, jsdom shares that object, and its getter reads as undefined without --localstorage-file, which failed 229 tests across 28 unrelated suites on CI. Closes #1015
BookOrbit - Client
Vue 3 SPA built with Vite and Tailwind CSS v4.
Running
From the repo root: pnpm dev (starts both server and client).
Client only: pnpm dev (from this directory). Runs at http://localhost:5173.
The Vite dev server proxies /api and /socket.io requests to the backend at localhost:3000.
IDE setup
- VS Code: Install the Vue (Official) extension. Disable Vetur if installed.
- WebStorm / IntelliJ: Vue support is built in. Enable TypeScript service for
.vuefiles. - Browser: Install Vue.js devtools and enable Custom Object Formatters in DevTools settings.
Project layout
src/
├── features/ Feature modules (one folder per domain)
│ ├── auth/ Login, registration, password reset
│ ├── book/ Book detail, covers, metadata
│ ├── library/ Library management
│ ├── collection/ Book collections
│ ├── smart-scope/ Saved search views
│ ├── scanner/ Scan progress UI
│ ├── reader/ Book reader (epub, pdf, cbz)
│ ├── settings/ User settings
│ └── admin/ Admin panel (users, roles, settings)
├── components/ Shared components (header, sidebar, icons)
│ └── ui/ Reusable UI primitives (button, dialog, etc.)
├── composables/ Global composables
├── views/ Route-level page components
├── router/ Vue Router config and guards
├── lib/ Utilities (api client, helpers)
├── stores/ Pinia stores (theme only - prefer composables)
└── assets/ CSS, fonts, static assets
Testing
pnpm test:unit # run unit tests
pnpm test:cov # run unit tests with coverage
Key conventions
- All components use
<script setup lang="ts">(Composition API only). - Feature state lives in composables (
features/<name>/composables/use*.ts), not global stores. - HTTP calls use the native
fetchAPI viasrc/lib/api.ts. - Styling with Tailwind CSS v4 utility classes. Theme tokens are CSS variables in
src/assets/main.css. - Icons from
@lucide/vueonly. - Shared types imported from
@bookorbit/types.