This commit is contained in:
seb
2026-08-07 04:05:01 +02:00
parent 4833acd680
commit 1e89e19863
22 changed files with 1433 additions and 2 deletions

181
API.article.md Normal file
View File

@@ -0,0 +1,181 @@
# article
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `article.addImage`
*Source: `src/store/article/addImage.js`*
Adds an image to an article by its SKU, processing it into AVIF variants.
```js
const fn = addImage(pool);
const result = await fn(42, 'SKU-1', imageBuffer);
// => { picId, sort, full: { w, h, size }, thumb: { w, h }, fullHash, thumbHash }
```
## `article.createUnderParent`
*Source: `src/store/article/createUnderParent.js`*
Creates a new article under a given parent category, allocating a SKU and a default unit.
```js
const fn = createUnderParent(pool);
const article = await fn({ googleAuthId: 42, parentId: 5, name: 'Cola' });
// => { id, parentId, name, sku }
```
## `article.delete`
*Source: `src/store/article/delete.js`*
Deletes an article by its SKU, refusing when it still has children.
```js
const fn = del(pool);
await fn(42, 'SKU-1');
```
## `article.deleteImage`
*Source: `src/store/article/deleteImage.js`*
Deletes an image from an article by its SKU and full image hash.
```js
const fn = deleteImage(pool);
await fn(42, 'SKU-1', 'abc123');
```
## `article.getBySku`
*Source: `src/store/article/getBySku.js`*
Returns the full detail of an article by its SKU, including unit, brand, categories, photos, EANs and prices.
```js
const fn = getBySku(pool);
const article = await fn(42, 'SKU-1');
// => { article: { id, sku, name, unit, brand, categoryIds, photos, eans, prices, ... } }
```
## `article.getHistoryBySku`
*Source: `src/store/article/getHistoryBySku.js`*
Returns the change history of an article by its SKU.
```js
const fn = getHistoryBySku(pool);
const history = await fn(42, 'SKU-1');
// => [{ id, companyuserId, date, text }]
```
## `article.listExport`
*Source: `src/store/article/listExport.js`*
Returns articles for export, optionally scoped to a category, including category breadcrumbs and image hashes.
```js
const fn = listExport(pool);
const articles = await fn(42, 1, null);
// => [{ id, sku, name, slug, unitSi, net, taxRate, eans, categoryBreadcrumbs, fullHashes, ... }]
```
## `article.listSearchIndex`
*Source: `src/store/article/listSearchIndex.js`*
Returns a lightweight search index of all articles for a company.
```js
const fn = listSearchIndex(pool);
const articles = await fn(42, 1);
// => [{ id, sku, name, eans, categoryIds }]
```
## `article.orderImages`
*Source: `src/store/article/orderImages.js`*
Reorders the images of an article by its SKU.
```js
const fn = orderImages(pool);
const result = await fn(42, 'SKU-1', { fullHashes: ['a', 'b'] });
// => { fullHashes: ['a', 'b'] }
```
## `article.setBrandIdBySku`
*Source: `src/store/article/setBrandIdBySku.js`*
Sets (or clears) the brand of an article by its SKU.
```js
const fn = setBrandIdBySku(pool);
const article = await fn(42, 'SKU-1', 3);
// => { id, sku, name, ... }
```
## `article.setCategoryIdsBySku`
*Source: `src/store/article/setCategoryIdsBySku.js`*
Replaces the category membership of an article by its SKU.
```js
const fn = setCategoryIdsBySku(pool);
const article = await fn(42, 'SKU-1', [5, 9]);
// => { id, sku, name, ... }
```
## `article.setEansBySku`
*Source: `src/store/article/setEansBySku.js`*
Replaces the EAN list of an article by its SKU.
```js
const fn = setEansBySku(pool);
const article = await fn(42, 'SKU-1', ['4001234567890']);
// => { id, sku, name, ... }
```
## `article.setPricesBySku`
*Source: `src/store/article/setPricesBySku.js`*
Replaces the price list of an article by its SKU.
```js
const fn = setPricesBySku(pool);
const article = await fn(42, 'SKU-1', [{ price: 1.5, tax: 19, minmultiplier: 1 }]);
// => { id, sku, name, ... }
```
## `article.setWeightBySku`
*Source: `src/store/article/setWeightBySku.js`*
Sets the weight of an article by its SKU.
```js
const fn = setWeightBySku(pool);
const article = await fn(42, 'SKU-1', 1.5);
// => { id, sku, name, ... }
```
## `article.updateBySku`
*Source: `src/store/article/updateBySku.js`*
Updates an article's name and/or unit (SI and amount), recording history.
```js
const fn = updateBySku(pool);
const article = await fn(42, 'SKU-1', { name: 'Cola 1L', unitSi: 'l', unitamount: 1 });
// => { id, sku, name, ... }
```

38
API.brand.md Normal file
View File

@@ -0,0 +1,38 @@
# brand
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `brand.delete`
*Source: `src/store/brand/delete.js`*
Deletes a brand for a company by its id.
```js
const fn = del(pool);
await fn(42, 1, 3);
```
## `brand.list`
*Source: `src/store/brand/list.js`*
Lists the brands of a company.
```js
const fn = list(pool);
const brands = await fn(42, 1);
// => [{ id, name, gsprpinfo }]
```
## `brand.upsert`
*Source: `src/store/brand/upsert.js`*
Creates or updates a brand for a company, keyed by name.
```js
const fn = upsert(pool);
const brand = await fn(42, 1, { name: 'Coca-Cola', gsprpinfo: 'x' });
// => { id, name, gsprpinfo }
```

110
API.category.md Normal file
View File

@@ -0,0 +1,110 @@
# category
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `category.addImage`
*Source: `src/store/category/addImage.js`*
Adds an image to a category, processing it into AVIF full and thumb variants.
```js
const fn = addImage(pool);
const result = await fn(42, 5, imageBuffer);
// => { id, fullHash, thumbW, thumbH, thumbHash }
```
## `category.createUnderParent`
*Source: `src/store/category/createUnderParent.js`*
Creates a new category under a given parent category.
```js
const fn = createUnderParent(pool);
const category = await fn({ googleAuthId: 42, parentId: 5, name: 'Drinks' });
// => { id, parentId, sort, name, slug }
```
## `category.delete`
*Source: `src/store/category/delete.js`*
Deletes a category, refusing to delete the company's root category.
```js
const fn = del(pool);
await fn({ googleAuthId: 42, id: 5 });
```
## `category.deleteImage`
*Source: `src/store/category/deleteImage.js`*
Deletes the image of a category.
```js
const fn = deleteImage(pool);
const result = await fn(42, 5);
// => { id, thumbW: null, thumbH: null, thumbHash: null }
```
## `category.getCategoryArticles`
*Source: `src/store/category/getCategoryArticles.js`*
Returns the articles belonging to a single category.
```js
const fn = getCategoryArticles(pool);
const articles = await fn(42, 5);
// => [{ id, sku, name, ... }]
```
## `category.getTreeForCompany`
*Source: `src/store/category/getTreeForCompany.js`*
Returns the full category tree for a company together with its articles and the posterminal ids assigned to each category.
```js
const fn = getTreeForCompany(pool);
const tree = await fn(42, 1);
// => { languageId, tree: [{ id, posterminalIds, ... }], articles: [...] }
```
## `category.move`
*Source: `src/store/category/move.js`*
Moves a category to a new parent, preventing cycles and cross-company moves.
```js
const fn = move(pool);
const result = await fn({ googleAuthId: 42, id: 5, parentId: 9 });
// => { id, parentId, sort }
```
## `category.order`
*Source: `src/store/category/order.js`*
Reorders the child categories of a given parent.
```js
const fn = order(pool);
const result = await fn({ googleAuthId: 42, parentId: 5, categoryIds: [3, 1, 2] });
// => { categoryIds: [3, 1, 2] }
```
## `category.rename`
*Source: `src/store/category/rename.js`*
Renames a category and updates its slug.
```js
const fn = rename(pool);
const result = await fn({ googleAuthId: 42, id: 5, name: 'Soft Drinks' });
// => { id, name, slug }
```

80
API.company.md Normal file
View File

@@ -0,0 +1,80 @@
# company
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `company.create`
*Source: `src/store/company/create.js`*
Creates a new company together with its root category, POS customer group, default language and tax rates, and links it to the given Google auth user.
```js
const fn = create(pool);
const company = await fn({
iso639: 'de',
name: 'Acme',
taxrate: 19,
reducedtaxrate: 7,
googleAuthId: 42,
});
// => { id, rootCategoryId, languageId, taxrateId, reducedtaxrateId, taxfreerateId, posCustomerGroupId }
```
## `company.delete`
*Source: `src/store/company/delete.js`*
Deletes a company by its id.
```js
const fn = del(pool);
await fn(1);
```
## `company.getById`
*Source: `src/store/company/getById.js`*
Returns a single company by its id.
```js
const fn = getById(pool);
const company = await fn(1);
// => { id, name, ... }
```
## `company.getByName`
*Source: `src/store/company/getByName.js`*
Returns a single company by its name.
```js
const fn = getByName(pool);
const company = await fn('Acme');
// => { id, name, ... }
```
## `company.list`
*Source: `src/store/company/list.js`*
Lists the companies accessible to the given Google auth user.
```js
const fn = list(pool);
const companies = await fn(42);
// => [{ id, name, ... }]
```
## `company.update`
*Source: `src/store/company/update.js`*
Updates an existing company's name, language and tax rates.
```js
const fn = update(pool);
const result = await fn(1, { iso639: 'de', name: 'Acme', taxrate: 19, reducedtaxrate: 7 });
// => { id, rootCategoryId, languageId, taxrateId, reducedtaxrateId, taxfreerateId }
```

50
API.companysetting.md Normal file
View File

@@ -0,0 +1,50 @@
# companysetting
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `companysetting.delete`
*Source: `src/store/companysetting/delete.js`*
Deletes a company setting by key.
```js
const fn = del(pool);
await fn(42, 1, 'theme');
```
## `companysetting.get`
*Source: `src/store/companysetting/get.js`*
Returns a single company setting by key.
```js
const fn = get(pool);
const setting = await fn(42, 1, 'theme');
// => { key, value, frontend }
```
## `companysetting.list`
*Source: `src/store/companysetting/list.js`*
Lists the settings of a company, optionally only frontend-visible ones.
```js
const fn = list(pool);
const settings = await fn(42, 1, { frontendOnly: true });
// => [{ key, value, frontend }]
```
## `companysetting.set`
*Source: `src/store/companysetting/set.js`*
Sets (upserts) a company setting by key.
```js
const fn = set(pool);
const setting = await fn(42, 1, { key: 'theme', value: 'dark', frontend: true });
// => { key, value, frontend }
```

38
API.companyuser.md Normal file
View File

@@ -0,0 +1,38 @@
# companyuser
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `companyuser.add`
*Source: `src/store/companyuser/add.js`*
Adds a company user linking a company to a Google auth account.
```js
const fn = add(pool);
const id = await fn(1, 42);
// => 7
```
## `companyuser.delete`
*Source: `src/store/companyuser/delete.js`*
Deletes a company user link by its id.
```js
const fn = del(pool);
await fn(7);
```
## `companyuser.getByEmail`
*Source: `src/store/companyuser/getByEmail.js`*
Returns the company user ids associated with the given email address.
```js
const fn = getByEmail(pool);
const ids = await fn('user@example.com');
// => [1, 2, 3]
```

62
API.customergroup.md Normal file
View File

@@ -0,0 +1,62 @@
# customergroup
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `customergroup.create`
*Source: `src/store/customergroup/create.js`*
Creates a new customer group for a company.
```js
const fn = create(pool);
const group = await fn(42, 1, { name: 'Wholesale' });
// => { id, name, sort }
```
## `customergroup.delete`
*Source: `src/store/customergroup/delete.js`*
Deletes a customer group for a company by its id.
```js
const fn = del(pool);
await fn(42, 1, 5);
```
## `customergroup.list`
*Source: `src/store/customergroup/list.js`*
Lists the customer groups of a company.
```js
const fn = list(pool);
const groups = await fn(42, 1);
// => [{ id, name, sort }]
```
## `customergroup.order`
*Source: `src/store/customergroup/order.js`*
Reorders the customer groups of a company.
```js
const fn = order(pool);
const result = await fn(42, 1, { customergroupIds: [3, 1, 2] });
// => { customergroupIds: [3, 1, 2] }
```
## `customergroup.update`
*Source: `src/store/customergroup/update.js`*
Updates the name of a customer group for a company.
```js
const fn = update(pool);
const group = await fn(42, 1, 5, { name: 'Retail' });
// => { id, name, sort }
```

62
API.delivery.md Normal file
View File

@@ -0,0 +1,62 @@
# delivery
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `delivery.create`
*Source: `src/store/delivery/create.js`*
Creates a new delivery for a company with its lines.
```js
const fn = create(pool);
const delivery = await fn(42, 1, { number: 'D-1', date: '2026-01-01', supplierId: 5, lines: [...] });
// => { id, number, type, entityId, date, lines: [...] }
```
## `delivery.delete`
*Source: `src/store/delivery/delete.js`*
Deletes a delivery by its id within a company.
```js
const fn = del(pool);
await fn(42, 1, 5);
```
## `delivery.getById`
*Source: `src/store/delivery/getById.js`*
Returns a single delivery by its id within a company.
```js
const fn = getById(pool);
const delivery = await fn(42, 1, 5);
// => { id, number, type, entityId, date, lines: [...] }
```
## `delivery.list`
*Source: `src/store/delivery/list.js`*
Lists the deliveries of a company.
```js
const fn = list(pool);
const deliveries = await fn(42, 1);
// => [{ id, number, type, entityId, date }]
```
## `delivery.update`
*Source: `src/store/delivery/update.js`*
Updates a delivery's header and/or lines.
```js
const fn = update(pool);
const delivery = await fn(42, 1, 5, { number: 'D-2', lines: [...] });
// => { id, number, type, entityId, date, lines: [...] }
```

62
API.entity.md Normal file
View File

@@ -0,0 +1,62 @@
# entity
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `entity.create`
*Source: `src/store/entity/create.js`*
Creates a new entity (customer) in a customer group, recording history.
```js
const fn = create(pool);
const entity = await fn(42, 1, { customergroupId: 5, name: 'Doe', firstName: 'John' });
// => { id, customergroupId, firstName, name, createdAt, updatedAt }
```
## `entity.delete`
*Source: `src/store/entity/delete.js`*
Deletes an entity by its id within a company.
```js
const fn = del(pool);
await fn(42, 1, 5);
```
## `entity.getById`
*Source: `src/store/entity/getById.js`*
Returns a single entity by its id within a company.
```js
const fn = getById(pool);
const entity = await fn(42, 1, 5);
// => { id, customergroupId, firstName, name, createdAt, updatedAt }
```
## `entity.list`
*Source: `src/store/entity/list.js`*
Lists the entities (customers) of a company, optionally filtered by customer group or restricted to the 'customer' role.
```js
const fn = list(pool);
const entities = await fn(42, 1, { customergroupId: 5 });
// => [{ id, customergroupId, firstName, name, createdAt, updatedAt }]
```
## `entity.update`
*Source: `src/store/entity/update.js`*
Updates the name and/or first name of an entity, recording history.
```js
const fn = update(pool);
const entity = await fn(42, 1, 5, { name: 'Doe', firstName: 'Jane' });
// => { id, customergroupId, firstName, name, createdAt, updatedAt }
```

50
API.entityaddress.md Normal file
View File

@@ -0,0 +1,50 @@
# entityaddress
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `entityaddress.create`
*Source: `src/store/entityaddress/create.js`*
Creates a new address for an entity.
```js
const fn = create(pool);
const address = await fn(42, 1, 5, { addressType: 'billing', street: 'Main St', city: 'Berlin' });
// => { id, entityId, firstName, name, street, streetNumber, zip, city, county, addressType, sort }
```
## `entityaddress.delete`
*Source: `src/store/entityaddress/delete.js`*
Deletes an address of an entity.
```js
const fn = del(pool);
await fn(42, 1, 5, 9);
```
## `entityaddress.list`
*Source: `src/store/entityaddress/list.js`*
Lists the addresses of an entity.
```js
const fn = list(pool);
const addresses = await fn(42, 1, 5);
// => [{ id, entityId, firstName, name, street, streetNumber, zip, city, county, addressType, sort }]
```
## `entityaddress.update`
*Source: `src/store/entityaddress/update.js`*
Updates an address of an entity.
```js
const fn = update(pool);
const address = await fn(42, 1, 5, 9, { city: 'Hamburg' });
// => { id, entityId, firstName, name, street, streetNumber, zip, city, county, addressType, sort }
```

50
API.entitycontact.md Normal file
View File

@@ -0,0 +1,50 @@
# entitycontact
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `entitycontact.create`
*Source: `src/store/entitycontact/create.js`*
Creates a new contact for an entity.
```js
const fn = create(pool);
const contact = await fn(42, 1, 5, { contactType: 'email', contact: 'a@b.c' });
// => { id, entityId, contactType, contact, sort }
```
## `entitycontact.delete`
*Source: `src/store/entitycontact/delete.js`*
Deletes a contact of an entity.
```js
const fn = del(pool);
await fn(42, 1, 5, 9);
```
## `entitycontact.list`
*Source: `src/store/entitycontact/list.js`*
Lists the contacts of an entity.
```js
const fn = list(pool);
const contacts = await fn(42, 1, 5);
// => [{ id, entityId, contactType, contact, sort }]
```
## `entitycontact.update`
*Source: `src/store/entitycontact/update.js`*
Updates a contact of an entity.
```js
const fn = update(pool);
const contact = await fn(42, 1, 5, 9, { contact: 'b@c.d' });
// => { id, entityId, contactType, contact, sort }
```

84
API.google_auth.md Normal file
View File

@@ -0,0 +1,84 @@
# google_auth
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `google_auth.add`
*Source: `src/store/google_auth/add.js`*
Adds a new allowed Google auth email.
```js
const fn = add(pool);
const id = await fn('user@example.com');
// => 1
```
## `google_auth.getByEmail`
*Source: `src/store/google_auth/getByEmail.js`*
Returns a Google auth row by email.
```js
const fn = getByEmail(pool);
const auth = await fn('user@example.com');
// => { id, email, ... }
```
## `google_auth.getById`
*Source: `src/store/google_auth/getById.js`*
Returns a Google auth row by its id.
```js
const fn = getById(pool);
const auth = await fn(42);
// => { id, email, ... }
```
## `google_auth.listAllowedEmails`
*Source: `src/store/google_auth/listAllowedEmails.js`*
Lists all allowed Google auth emails.
```js
const fn = listAllowedEmails(pool);
const emails = await fn();
// => [{ id, email }]
```
## `google_auth.removeAllowedEmail`
*Source: `src/store/google_auth/removeAllowedEmail.js`*
Removes an allowed Google auth email.
```js
const fn = removeAllowedEmail(pool);
await fn('user@example.com');
```
## `google_auth.setProfile`
*Source: `src/store/google_auth/setProfile.js`*
Updates the profile (picture, picture binary, sub) of a Google auth user.
```js
const fn = setProfile(pool);
await fn(42, { picture: 'url', pictureBinary: buffer, sub: 'sub' });
```
## `google_auth.setSelectedCompany`
*Source: `src/store/google_auth/setSelectedCompany.js`*
Sets the currently selected company for a Google auth user.
```js
const fn = setSelectedCompany(pool);
await fn(42, 1);
```

62
API.lang.md Normal file
View File

@@ -0,0 +1,62 @@
# lang
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `lang.create`
*Source: `src/store/lang/create.js`*
Creates a new language by its ISO 639 code.
```js
const fn = create(pool);
const id = await fn('de');
// => 1
```
## `lang.delete`
*Source: `src/store/lang/delete.js`*
Deletes a language by its id.
```js
const fn = del(pool);
await fn(1);
```
## `lang.ensure`
*Source: `src/store/lang/ensure.js`*
Returns the id of a language by ISO code, creating it if it does not exist.
```js
const fn = ensure(pool);
const id = await fn('de');
// => 1
```
## `lang.getByIso639`
*Source: `src/store/lang/getByIso639.js`*
Returns a language row by its ISO 639 code.
```js
const fn = getByIso639(pool);
const lang = await fn('de');
// => { id, iso639 }
```
## `lang.list`
*Source: `src/store/lang/list.js`*
Lists all languages.
```js
const fn = list(pool);
const languages = await fn();
// => [{ id, iso639 }]
```

26
API.md Normal file
View File

@@ -0,0 +1,26 @@
# LibDashStore API
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each method is an async function that takes a `pool` (mssql connection pool) at construction time and returns a callable function. Methods are grouped by the namespace they are exposed under.
## Table of Contents
- [companyuser](API.companyuser.md)
- [company](API.company.md)
- [category](API.category.md)
- [article](API.article.md)
- [lang](API.lang.md)
- [tax](API.tax.md)
- [unit](API.unit.md)
- [companysetting](API.companysetting.md)
- [brand](API.brand.md)
- [customergroup](API.customergroup.md)
- [entity](API.entity.md)
- [entityaddress](API.entityaddress.md)
- [entitycontact](API.entitycontact.md)
- [supplier](API.supplier.md)
- [delivery](API.delivery.md)
- [posterminal](API.posterminal.md)
- [google_auth](API.google_auth.md)
- [pic](API.pic.md)

27
API.pic.md Normal file
View File

@@ -0,0 +1,27 @@
# pic
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `pic.getImageByHash`
*Source: `src/store/pic/getImageByHash.js`*
Returns the full-size image (AVIF) for a given hash.
```js
const fn = getImageByHash(pool);
const image = await fn(42, 'abc123');
// => { buffer, w, h, size, contentType: 'image/avif' }
```
## `pic.getThumbByHash`
*Source: `src/store/pic/getThumbByHash.js`*
Returns the thumbnail image (AVIF) for a given hash.
```js
const fn = getThumbByHash(pool);
const thumb = await fn(42, 'abc123');
// => { buffer, w, h, contentType: 'image/avif' }
```

86
API.posterminal.md Normal file
View File

@@ -0,0 +1,86 @@
# posterminal
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `posterminal.delete`
*Source: `src/store/posterminal/delete.js`*
Deletes a posterminal by its id within a company.
```js
const fn = del(pool);
await fn(42, 1, 5);
```
## `posterminal.list`
*Source: `src/store/posterminal/list.js`*
Lists the posterminals of a company.
```js
const fn = list(pool);
const terminals = await fn(42, 1);
// => [{ id, name, token, pairingpin }]
```
## `posterminal.setOff`
*Source: `src/store/posterminal/setOff.js`*
Removes a category assignment from a posterminal (turns it off).
```js
const fn = setOff(pool);
const result = await fn(42, 1, 5, 9);
// => { id, categoryIds: [...] }
```
## `posterminal.setOffAll`
*Source: `src/store/posterminal/setOffAll.js`*
Removes all category assignments from a posterminal.
```js
const fn = setOffAll(pool);
const result = await fn(42, 1, 5);
// => { id, categoryIds: [] }
```
## `posterminal.setOn`
*Source: `src/store/posterminal/setOn.js`*
Assigns a category to a posterminal (turns it on for that category).
```js
const fn = setOn(pool);
const result = await fn(42, 1, 5, 9);
// => { id, categoryIds: [9, ...] }
```
## `posterminal.setOnAll`
*Source: `src/store/posterminal/setOnAll.js`*
Assigns all categories of a company to a posterminal.
```js
const fn = setOnAll(pool);
const result = await fn(42, 1, 5);
// => { id, categoryIds: [...] }
```
## `posterminal.upsert`
*Source: `src/store/posterminal/upsert.js`*
Creates or updates a posterminal for a company.
```js
const fn = upsert(pool);
const terminal = await fn(42, 1, { name: 'Kasse 1', pairingpin: '1234', token: 'abc' });
// => { id, name, token, pairingpin }
```

50
API.supplier.md Normal file
View File

@@ -0,0 +1,50 @@
# supplier
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `supplier.create`
*Source: `src/store/supplier/create.js`*
Creates a new supplier for a company, recording history.
```js
const fn = create(pool);
const supplier = await fn(42, 1, { name: 'Acme Supplies' });
// => { id, name, createdAt, updatedAt }
```
## `supplier.delete`
*Source: `src/store/supplier/delete.js`*
Deletes a supplier by its id within a company.
```js
const fn = del(pool);
await fn(42, 1, 5);
```
## `supplier.list`
*Source: `src/store/supplier/list.js`*
Lists the suppliers of a company.
```js
const fn = list(pool);
const suppliers = await fn(42, 1);
// => [{ id, name, createdAt, updatedAt }]
```
## `supplier.update`
*Source: `src/store/supplier/update.js`*
Updates the name of a supplier, recording history.
```js
const fn = update(pool);
const supplier = await fn(42, 1, 5, { name: 'Acme GmbH' });
// => { id, name, createdAt, updatedAt }
```

51
API.tax.md Normal file
View File

@@ -0,0 +1,51 @@
# tax
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `tax.create`
*Source: `src/store/tax/create.js`*
Creates a new tax rate.
```js
const fn = create(pool);
const id = await fn(19);
// => 1
```
## `tax.ensure`
*Source: `src/store/tax/ensure.js`*
Returns the id of a tax rate, creating it if it does not exist.
```js
const fn = ensure(pool);
const id = await fn(19);
// => 1
```
## `tax.getByRate`
*Source: `src/store/tax/getByRate.js`*
Returns a tax row by its rate.
```js
const fn = getByRate(pool);
const tax = await fn(19);
// => { id, rate }
```
## `tax.list`
*Source: `src/store/tax/list.js`*
Lists all tax rates.
```js
const fn = list(pool);
const taxes = await fn();
// => [{ id, rate }]
```

38
API.unit.md Normal file
View File

@@ -0,0 +1,38 @@
# unit
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
## `unit.delete`
*Source: `src/store/unit/delete.js`*
Deletes a unit for a company by its SI code.
```js
const fn = del(pool);
await fn(42, 1, 'l');
```
## `unit.list`
*Source: `src/store/unit/list.js`*
Lists the units available for a company.
```js
const fn = list(pool);
const units = await fn(42, 1);
// => [{ id, si, basesi, basesifactor, symbol, name }]
```
## `unit.upsert`
*Source: `src/store/unit/upsert.js`*
Creates or updates a unit for a company, keyed by its SI code.
```js
const fn = upsert(pool);
const unit = await fn(42, 1, { si: 'l', basesi: 'm3', basesifactor: 0.001, symbol: 'L', name: 'Liter' });
// => { id, si, basesi, basesifactor, symbol, name }
```

View File

@@ -20,8 +20,6 @@ ID fields in the JS API use camelCase `…Id` (DB columns stay snake_case). `goo
## Schema
**Kein Migrations-Code:** Wir gehen von einer frischen DB aus (`npm run reset-db`). Schema nur in `src/schema.js`; Anpassungen an einer laufenden DB manuell per `sqlcmd`, nicht im Repo.
| Method | Description |
| --- | --- |
| `initialize()` | Runs all `SCHEMA_SCRIPTS` (`IF NOT EXISTS`). Does **not** purge. |

225
generate-api-doc.js Normal file
View File

@@ -0,0 +1,225 @@
import { readdirSync, readFileSync, writeFileSync, statSync } from 'node:fs';
import { dirname, join } from 'node:path';
import { fileURLToPath } from 'node:url';
const __dirname = dirname(fileURLToPath(import.meta.url));
const storeDir = join(__dirname, 'src', 'store');
const outputPath = join(__dirname, 'API.md');
// Modules that are exposed on the LibDashStore instance (from src/index.js).
// Order here controls the order of sections in the generated document.
const MODULE_ORDER = [
'companyuser',
'company',
'category',
'article',
'lang',
'tax',
'unit',
'companysetting',
'brand',
'customergroup',
'entity',
'entityaddress',
'entitycontact',
'supplier',
'delivery',
'quote',
'order',
'posterminal',
'google_auth',
'pic',
];
// Files that are internal helpers and should not appear as public API entries.
const INTERNAL_FILES = new Set([
'request.js',
'slugify.js',
'initialize.js',
'purge.js',
'helpers.js',
'writeLines.js',
'shapeSetting.js',
'shapeUnit.js',
'ensureDefault.js',
'ensureLieferantenGroup.js',
'resolveCompanyAccess.js',
'resolveCategoryAccess.js',
'resolveCustomerGroupAccess.js',
'resolveEntityAccess.js',
'resolvePicAccess.js',
'resolveArticleBySku.js',
'queryBySku.js',
'queryCategoryArticles.js',
'getCategoryPosterminalIds.js',
'nextSku.js',
'createStore.js',
'index.js',
]);
/**
* Extract the leading JSDoc block from a source string.
* @param {string} source
* @returns {{ description: string, example: string } | null}
*/
function extractJsDoc(source) {
const match = source.match(/\/\*\*([\s\S]*?)\*\//);
if (!match) return null;
const block = match[1];
const lines = block
.split('\n')
.map((l) => l.replace(/^\s*\*\s?/, '').replace(/^\s*\*/, ''));
const description = [];
const example = [];
let inExample = false;
for (const line of lines) {
if (line.trim() === '@example') {
inExample = true;
continue;
}
if (line.trim().startsWith('@')) {
inExample = false;
continue;
}
if (inExample) {
example.push(line);
} else if (line.trim()) {
description.push(line.trim());
}
}
return {
description: description.join(' ').trim(),
example: example.join('\n').trim(),
};
}
/**
* Recursively collect all .js files under a directory.
* @param {string} dir
* @returns {string[]} absolute file paths
*/
function collectFiles(dir) {
const out = [];
for (const entry of readdirSync(dir)) {
const full = join(dir, entry);
if (statSync(full).isDirectory()) {
out.push(...collectFiles(full));
} else if (entry.endsWith('.js')) {
out.push(full);
}
}
return out;
}
/**
* Build a map of module name -> array of { name, file, description, example }.
* @returns {Map<string, Array<object>>}
*/
function buildModules() {
const modules = new Map();
for (const file of collectFiles(storeDir)) {
const rel = file.slice(storeDir.length + 1).split('/');
const moduleName = rel[0];
const fileName = rel[rel.length - 1];
if (INTERNAL_FILES.has(fileName)) continue;
const source = readFileSync(file, 'utf8');
const doc = extractJsDoc(source);
if (!doc) continue;
const fnName = fileName.replace(/\.js$/, '');
if (!modules.has(moduleName)) {
modules.set(moduleName, []);
}
modules.get(moduleName).push({
name: fnName,
file: rel.join('/'),
description: doc.description,
example: doc.example,
});
}
return modules;
}
function renderSection(moduleName, entries) {
const lines = [];
lines.push(`# ${moduleName}`);
lines.push('');
lines.push(
'This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.',
);
lines.push('');
for (const entry of entries) {
lines.push(`## \`${moduleName}.${entry.name}\``);
lines.push('');
lines.push(`*Source: \`src/store/${entry.file}\`*`);
lines.push('');
if (entry.description) {
lines.push(entry.description);
lines.push('');
}
if (entry.example) {
lines.push('```js');
lines.push(entry.example);
lines.push('```');
lines.push('');
}
}
return lines.join('\n');
}
function render() {
const modules = buildModules();
const ordered = MODULE_ORDER.filter((m) => modules.has(m));
const extra = [...modules.keys()].filter((m) => !MODULE_ORDER.includes(m)).sort();
const moduleNames = [...ordered, ...extra];
// Write one file per section: API.<section>.md
const written = [];
for (const moduleName of moduleNames) {
const sectionPath = join(__dirname, `API.${moduleName}.md`);
const markdown = renderSection(moduleName, modules.get(moduleName));
writeFileSync(sectionPath, markdown, 'utf8');
written.push({ moduleName, sectionPath, bytes: markdown.length });
}
// Write the index API.md linking to each section file.
const lines = [];
lines.push('# LibDashStore API');
lines.push('');
lines.push(
'This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.',
);
lines.push('');
lines.push(
'The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each method is an async function that takes a `pool` (mssql connection pool) at construction time and returns a callable function. Methods are grouped by the namespace they are exposed under.',
);
lines.push('');
lines.push('## Table of Contents');
lines.push('');
for (const { moduleName } of written) {
lines.push(`- [${moduleName}](API.${moduleName}.md)`);
}
lines.push('');
return { index: lines.join('\n'), written };
}
const { index, written } = render();
writeFileSync(outputPath, index, 'utf8');
console.log(`Wrote ${outputPath} (${index.length} bytes)`);
for (const { moduleName, sectionPath, bytes } of written) {
console.log(`Wrote ${sectionPath} (${bytes} bytes)`);
}

View File

@@ -11,6 +11,7 @@
},
"scripts": {
"schema-graph": "node generate-schema-graph.js",
"api-doc": "node generate-api-doc.js",
"init-schema": "node scripts/init-schema.js",
"purge-db": "node scripts/purge-db.js",
"reset-db": "node scripts/reset-db.js",