# libdashstore MSSQL schema + domain API for Dash. One class, methods mirror the file path under `src/store/`. ```js import sql from 'mssql'; import LibDashStore from 'libdashstore'; const pool = await sql.connect({ /* … */ }); const client = await new LibDashStore(pool); // runs initialize() (ensure schema, no purge) ``` SQL lives in `src/sql/.js`. Schema DDL: `src/schema.js` / `import 'libdashstore/schema'`. --- ## Schema | Method | Description | | --- | --- | | `initialize()` | Runs all `SCHEMA_SCRIPTS` (`IF NOT EXISTS`). Does **not** purge. | | `purge()` | Drops all known tables + number procedure. | --- ## `company` | Method | Signature | Returns | | --- | --- | --- | | `create` | `({ iso639, name, taxrate, reducedtaxrate })` | result | | `update` | `(id, { iso639, name, taxrate, reducedtaxrate })` | result | | `delete` | `(companyId)` | `void` | | `list` | `()` | `result[]` | ### result (`create` / `update` / `list` items) ```ts { id: number // company id root_category_id: number language_id: number // language.id for iso639 taxrate: number // tax.id reducedtaxrate: number // tax.id taxfreerate: number // tax.id (rate 0; unchanged on update) } ``` ### `create` (transaction) For `POST /api/company`: 1. Fails if `name` is taken (`Company name not available`) 2. Ensures language by `iso639` (get or create) 3. Ensures tax rows for `taxrate`, `reducedtaxrate`, and `0` → `taxfreerate` 4. Creates root category (`parent_id = null`) 5. Inserts company with all FKs set ### `update` (transaction) For `PATCH /api/company/:id`: 1. Fails if company missing / name taken by another company 2. Ensures lang + tax rates 3. Updates `name`, `default_language_id`, `taxrate`, `reducedtaxrate` (`taxfreerate` / root category unchanged) --- ## `google_auth` | Method | Signature | Returns | | --- | --- | --- | | `add` | `(email)` | `number` (auth id) | | `getById` | `(id)` | `row \| undefined` | | `getByEmail` | `(email)` | `row \| undefined` | | `setSelectedCompany` | `(authId, companyId)` | `void` | | `list` | `()` | `row[]` | | `del` | `(id)` | `void` | ### Row shape ```ts { id: number email: string created_at: Date selected_company: number | null } ``` Backend mapping: - Login: `getByEmail(email)` ← `getAllowedEmail` - Auth middleware: `getById(id)` ← `getAllowedEmailById` - `PUT /api/auth/selected-company`: `setSelectedCompany(authId, companyId)` --- ## `companyuser` | Method | Signature | Returns | | --- | --- | --- | | `add` | `(companyId, authId)` | `number` (companyuser id) | | `getByEmail` | `(email)` | `number[]` (companyuser ids) | | `delete` | `(id)` | `void` | --- ## `lang` | Method | Signature | Returns | | --- | --- | --- | | `create` | `(iso639)` | `number` | | `getByIso639` | `(iso639)` | `{ id, iso639 } \| undefined` | | `ensure` | `(iso639, tx?)` | `number` (existing or new id) | | `list` | `()` | `{ id, iso639 }[]` | | `delete` | `(id)` | `void` | --- ## `tax` | Method | Signature | Returns | | --- | --- | --- | | `create` | `(rate)` | `number` | | `getByRate` | `(rate)` | `{ id, rate } \| undefined` | | `ensure` | `(rate, tx?)` | `number` (existing or new id) | | `list` | `()` | `{ id, rate }[]` | --- ## `category` | Method | Signature | Returns | | --- | --- | --- | | `create` | `({ parent_id, sort })` | `number` | | `updateParentId` | `(id, parentId)` | `void` | | `delete` | `(id)` | `void` | | `getTree` | `(rootId)` | `{ id, parent_id, sort }[]` (flat CTE result) | --- ## Backend route cheatsheet | Route | Store call | | --- | --- | | `POST /api/company` | `company.create({ iso639, name, taxrate, reducedtaxrate })` | | `PATCH /api/company/:id` | `company.update(id, { iso639, name, taxrate, reducedtaxrate })` | | `DELETE /api/company/:id` | `company.delete(id)` | | `PUT /api/auth/selected-company` | `google_auth.setSelectedCompany(authId, companyId)` | --- ## Scripts ```bash npm run init-schema # apply SCHEMA_SCRIPTS via .env npm run test:api # interactive API tester npm run schema-graph # regenerate schema-graph.svg ``` Env: `MSSQL_SERVER`, `MSSQL_DATABASE`, `MSSQL_USER`, `MSSQL_PASSWORD`.