feat: manage files via manifestattachment with auth and cascade trigger, format API.md method signatures
This commit is contained in:
124
API.manifestattachment.md
Normal file
124
API.manifestattachment.md
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
# manifestattachment
|
||||||
|
|
||||||
|
This document is auto-generated from the JSDoc comments in `src/store` by running `npm run api-doc`.
|
||||||
|
|
||||||
|
## `manifestattachment.add`
|
||||||
|
|
||||||
|
*Source: `src/store/manifestattachment/add.js`*
|
||||||
|
|
||||||
|
Attaches a file to an existing manifest.
|
||||||
|
|
||||||
|
**Parameters**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `googleAuthId` | `number` | The id of the Google auth user. |
|
||||||
|
| `manifestId` | `number` | The id of the manifest. |
|
||||||
|
| `input` | `object` | The file data. |
|
||||||
|
| `input.mimetype` | `string` | The MIME type of the file (e.g. `'application/pdf'`). |
|
||||||
|
| `input.name` | `string` | The file name. |
|
||||||
|
| `input.content` | `Buffer` | The file content. |
|
||||||
|
|
||||||
|
**Returns**
|
||||||
|
|
||||||
|
`Promise<object>` — The created attachment record.
|
||||||
|
|
||||||
|
**Throws**
|
||||||
|
|
||||||
|
`Error` — If the manifest is not found or file input is invalid.
|
||||||
|
|
||||||
|
**Example**
|
||||||
|
|
||||||
|
```js
|
||||||
|
const attachment = await store.manifestattachment.add(42, 1, {
|
||||||
|
mimetype: 'application/pdf',
|
||||||
|
name: 'invoice.pdf',
|
||||||
|
content: fileBuffer,
|
||||||
|
});
|
||||||
|
// => { id, manifestId, fileId, mimetype, name }
|
||||||
|
```
|
||||||
|
|
||||||
|
## `manifestattachment.getById`
|
||||||
|
|
||||||
|
*Source: `src/store/manifestattachment/getById.js`*
|
||||||
|
|
||||||
|
Gets an attachment for a manifest by its attachment ID or file ID, including full file content.
|
||||||
|
|
||||||
|
**Parameters**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `googleAuthId` | `number` | The id of the Google auth user. |
|
||||||
|
| `manifestId` | `number` | The manifest ID. |
|
||||||
|
| `id` | `number` | The attachment ID or file ID. |
|
||||||
|
|
||||||
|
**Returns**
|
||||||
|
|
||||||
|
`Promise<object>` — The attachment record with binary content.
|
||||||
|
|
||||||
|
**Throws**
|
||||||
|
|
||||||
|
`Error` — If the manifest or attachment is not found, or user is not authorized.
|
||||||
|
|
||||||
|
**Example**
|
||||||
|
|
||||||
|
```js
|
||||||
|
const attachment = await store.manifestattachment.getById(42, 1, 5);
|
||||||
|
// => { id, manifestId, fileId, mimetype, name, content }
|
||||||
|
```
|
||||||
|
|
||||||
|
## `manifestattachment.listByManifestId`
|
||||||
|
|
||||||
|
*Source: `src/store/manifestattachment/listByManifestId.js`*
|
||||||
|
|
||||||
|
Lists all attachments for a given manifest, without loading their full binary content.
|
||||||
|
|
||||||
|
**Parameters**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `googleAuthId` | `number` | The id of the Google auth user. |
|
||||||
|
| `manifestId` | `number` | The manifest ID. |
|
||||||
|
|
||||||
|
**Returns**
|
||||||
|
|
||||||
|
`Promise<Array<object>>` — A list of attachment metadata objects.
|
||||||
|
|
||||||
|
**Throws**
|
||||||
|
|
||||||
|
`Error` — If the manifest is not found or the user is not authorized.
|
||||||
|
|
||||||
|
**Example**
|
||||||
|
|
||||||
|
```js
|
||||||
|
const attachments = await store.manifestattachment.listByManifestId(42, 1);
|
||||||
|
// => [{ id, manifestId, fileId, mimetype, name, size }]
|
||||||
|
```
|
||||||
|
|
||||||
|
## `manifestattachment.remove`
|
||||||
|
|
||||||
|
*Source: `src/store/manifestattachment/remove.js`*
|
||||||
|
|
||||||
|
Removes a file attachment from a manifest and deletes the underlying file.
|
||||||
|
|
||||||
|
**Parameters**
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `googleAuthId` | `number` | The id of the Google auth user. |
|
||||||
|
| `manifestId` | `number` | The manifest ID. |
|
||||||
|
| `id` | `number` | The attachment ID or file ID to remove. |
|
||||||
|
|
||||||
|
**Returns**
|
||||||
|
|
||||||
|
`Promise<void>`
|
||||||
|
|
||||||
|
**Throws**
|
||||||
|
|
||||||
|
`Error` — If the manifest or attachment is not found, or user is not authorized.
|
||||||
|
|
||||||
|
**Example**
|
||||||
|
|
||||||
|
```js
|
||||||
|
await store.manifestattachment.remove(42, 1, 5);
|
||||||
|
```
|
||||||
116
API.md
116
API.md
@@ -7,23 +7,139 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met
|
|||||||
## Table of Contents
|
## Table of Contents
|
||||||
|
|
||||||
- [companyuser](API.companyuser.md)
|
- [companyuser](API.companyuser.md)
|
||||||
|
- `add(companyId: number, googleAuthId: number): Promise<number>`
|
||||||
|
- `delete(id: number): Promise<void>`
|
||||||
|
- `getByEmail(email: string): Promise<Array<number>>`
|
||||||
- [company](API.company.md)
|
- [company](API.company.md)
|
||||||
|
- `create(input: object): Promise<{id: number, rootCategoryId: number, languageId: number, taxrateId: number, reducedtaxrateId: number, taxfreerateId: number, posCustomerGroupId: number}>`
|
||||||
|
- `delete(companyId: number): Promise<void>`
|
||||||
|
- `getById(id: number, tx?: object): Promise<object|undefined>`
|
||||||
|
- `getByName(name: string, tx?: object): Promise<object|undefined>`
|
||||||
|
- `list(googleAuthId: number): Promise<Array<object>>`
|
||||||
|
- `update(id: number, input: object): Promise<{id: number, rootCategoryId: number, languageId: number, taxrateId: number, reducedtaxrateId: number, taxfreerateId: number}>`
|
||||||
- [category](API.category.md)
|
- [category](API.category.md)
|
||||||
|
- `addImage(googleAuthId: number, categoryId: number, image: Buffer): Promise<{id: number, fullHash: string, thumbW: number, thumbH: number, thumbHash: string}>`
|
||||||
|
- `createUnderParent(input: object): Promise<{id: number, parentId: number, sort: number, name: string, slug: string}>`
|
||||||
|
- `delete(input: object): Promise<void>`
|
||||||
|
- `deleteImage(googleAuthId: number, categoryId: number): Promise<{id: number, thumbW: null, thumbH: null, thumbHash: null}>`
|
||||||
|
- `ensureByPath(input: object, tx?: object): Promise<number>`
|
||||||
|
- `getCategoryArticles(googleAuthId: number, categoryId: number): Promise<Array<object>>`
|
||||||
|
- `getTreeForCompany(googleAuthId: number): Promise<{languageId: number, tree: Array<object>, articles: Array<object>}>`
|
||||||
|
- `move(input: object): Promise<{id: number, parentId: number, sort: number}>`
|
||||||
|
- `order(input: object): Promise<{categoryIds: Array<number>}>`
|
||||||
|
- `rename(input: object): Promise<{id: number, name: string, slug: string}>`
|
||||||
- [article](API.article.md)
|
- [article](API.article.md)
|
||||||
|
- `addImage(googleAuthId: number, sku: string, image: Buffer): Promise<{picId: number, sort: number, full: {w: number, h: number, size: number}, thumb: {w: number, h: number}, fullHash: string, thumbHash: string}>`
|
||||||
|
- `createUnderParent(input: object): Promise<{id: number, parentId: number, name: string, sku: string}>`
|
||||||
|
- `delete(googleAuthId: number, sku: string): Promise<void>`
|
||||||
|
- `deleteImage(googleAuthId: number, sku: string, fullHash: string): Promise<void>`
|
||||||
|
- `getBySku(googleAuthId: number, sku: string): Promise<{article: object}>`
|
||||||
|
- `getHistoryBySku(googleAuthId: number, sku: string): Promise<Array<{id: number, companyuserId: number|null, date: string, text: string}>>`
|
||||||
|
- `importRows(input: object): Promise<{imported: Array<object>, skipped: Array<object>, errors: Array<object>}>`
|
||||||
|
- `listExport(googleAuthId: number, categoryId?: number|null): Promise<Array<object>>`
|
||||||
|
- `listSearchIndex(googleAuthId: number): Promise<Array<{id: number, sku: string, name: string, eans: Array<string>, categoryIds: Array<number>}>>`
|
||||||
|
- `orderImages(googleAuthId: number, sku: string, input: object): Promise<{fullHashes: Array<string>}>`
|
||||||
|
- `setBrandIdBySku(googleAuthId: number, sku: string, brandId: number|null): Promise<object>`
|
||||||
|
- `setCategoryIdsBySku(googleAuthId: number, sku: string, categoryIds: Array<number>): Promise<object>`
|
||||||
|
- `setEansBySku(googleAuthId: number, sku: string, eans: Array<string>): Promise<object>`
|
||||||
|
- `setFatherBySku(googleAuthId: number, sku: string, fatherSku: string|null): Promise<object>`
|
||||||
|
- `setPricesBySku(googleAuthId: number, sku: string, prices: Array<{price: number, tax: number, minmultiplier?: number}>): Promise<object>`
|
||||||
|
- `setWeightBySku(googleAuthId: number, sku: string, weight: number): Promise<object>`
|
||||||
|
- `updateBySku(googleAuthId: number, sku: string, patch: object): Promise<object>`
|
||||||
- [lang](API.lang.md)
|
- [lang](API.lang.md)
|
||||||
|
- `create(iso639: string, tx?: object): Promise<number>`
|
||||||
|
- `delete(id: number): Promise<void>`
|
||||||
|
- `ensure(iso639: string, tx?: object): Promise<number>`
|
||||||
|
- `getByIso639(iso639: string, tx?: object): Promise<{id: number, iso639: string}>`
|
||||||
|
- `list(): Promise<Array<{id: number, iso639: string}>>`
|
||||||
- [tax](API.tax.md)
|
- [tax](API.tax.md)
|
||||||
|
- `create(rate: number, tx?: object): Promise<number>`
|
||||||
|
- `ensure(rate: number, tx?: object): Promise<number>`
|
||||||
|
- `getByRate(rate: number, tx?: object): Promise<{id: number, rate: number}>`
|
||||||
|
- `list(): Promise<Array<{id: number, rate: number}>>`
|
||||||
- [unit](API.unit.md)
|
- [unit](API.unit.md)
|
||||||
|
- `delete(googleAuthId: number, si: string): Promise<void>`
|
||||||
|
- `list(googleAuthId: number): Promise<Array<{id: number, si: string, basesi: string, basesifactor: number, symbol: string, name: string}>>`
|
||||||
|
- `upsert(googleAuthId: number, input: object): Promise<{id: number, si: string, basesi: string, basesifactor: number, symbol: string, name: string}>`
|
||||||
- [companysetting](API.companysetting.md)
|
- [companysetting](API.companysetting.md)
|
||||||
|
- `get(googleAuthId: number, key: string, options?: object): Promise<{key: string, value: string, frontend: boolean, writeonly: boolean}|undefined>`
|
||||||
|
- `list(googleAuthId: number, options?: object): Promise<Array<{key: string, value: string, frontend: boolean, writeonly: boolean}>>`
|
||||||
|
- `set(googleAuthId: number, input: object): Promise<{key: string, value: string, frontend: boolean, writeonly: boolean}>`
|
||||||
- [brand](API.brand.md)
|
- [brand](API.brand.md)
|
||||||
|
- `delete(googleAuthId: number, id: number): Promise<void>`
|
||||||
|
- `list(googleAuthId: number): Promise<Array<{id: number, name: string, gsprpinfo: string|null}>>`
|
||||||
|
- `upsert(googleAuthId: number, input: object): Promise<{id: number, name: string, gsprpinfo: string|null}>`
|
||||||
- [customergroup](API.customergroup.md)
|
- [customergroup](API.customergroup.md)
|
||||||
|
- `create(googleAuthId: number, input: object): Promise<{id: number, name: string, sort: number}>`
|
||||||
|
- `delete(googleAuthId: number, id: number): Promise<void>`
|
||||||
|
- `list(googleAuthId: number): Promise<Array<{id: number, name: string, sort: number}>>`
|
||||||
|
- `order(googleAuthId: number, input: object): Promise<{customergroupIds: Array<number>}>`
|
||||||
|
- `update(googleAuthId: number, id: number, input: object): Promise<{id: number, name: string, sort: number}>`
|
||||||
- [entity](API.entity.md)
|
- [entity](API.entity.md)
|
||||||
|
- `create(googleAuthId: number, input: object): Promise<{id: number, customergroupId: number, firstName: string|null, name: string, number: string, createdAt: string, updatedAt: string}>`
|
||||||
|
- `delete(googleAuthId: number, id: number): Promise<void>`
|
||||||
|
- `getById(googleAuthId: number, id: number): Promise<{id: number, customergroupId: number, firstName: string|null, name: string, number: string, createdAt: string, updatedAt: string}>`
|
||||||
|
- `isNumberFree(googleAuthId: number, number: string, options?: object): Promise<boolean>`
|
||||||
|
- `list(googleAuthId: number, options?: object): Promise<Array<{id: number, customergroupId: number, firstName: string|null, name: string, number: string, createdAt: string, updatedAt: string}>>`
|
||||||
|
- `peekNextNumber(googleAuthId: number): Promise<string>`
|
||||||
|
- `update(googleAuthId: number, id: number, patch: object): Promise<{id: number, customergroupId: number, firstName: string|null, name: string, number: string, createdAt: string, updatedAt: string}>`
|
||||||
- [entityaddress](API.entityaddress.md)
|
- [entityaddress](API.entityaddress.md)
|
||||||
|
- `create(googleAuthId: number, entityId: number, input: object): Promise<object>`
|
||||||
|
- `delete(googleAuthId: number, entityId: number, id: number): Promise<void>`
|
||||||
|
- `list(googleAuthId: number, entityId: number): Promise<Array<object>>`
|
||||||
|
- `update(googleAuthId: number, entityId: number, id: number, patch: object): Promise<object>`
|
||||||
- [entitycontact](API.entitycontact.md)
|
- [entitycontact](API.entitycontact.md)
|
||||||
|
- `create(googleAuthId: number, entityId: number, input: object): Promise<{id: number, entityId: number, contactType: string, contact: string, sort: number}>`
|
||||||
|
- `delete(googleAuthId: number, entityId: number, id: number): Promise<void>`
|
||||||
|
- `list(googleAuthId: number, entityId: number): Promise<Array<{id: number, entityId: number, contactType: string, contact: string, sort: number}>>`
|
||||||
|
- `update(googleAuthId: number, entityId: number, id: number, patch: object): Promise<{id: number, entityId: number, contactType: string, contact: string, sort: number}>`
|
||||||
- [supplier](API.supplier.md)
|
- [supplier](API.supplier.md)
|
||||||
|
- `create(googleAuthId: number, input: object): Promise<{id: number, name: string, createdAt: string, updatedAt: string}>`
|
||||||
|
- `delete(googleAuthId: number, id: number): Promise<void>`
|
||||||
|
- `list(googleAuthId: number): Promise<Array<{id: number, name: string, createdAt: string, updatedAt: string}>>`
|
||||||
|
- `update(googleAuthId: number, id: number, input: object): Promise<{id: number, name: string, createdAt: string, updatedAt: string}>`
|
||||||
- [delivery](API.delivery.md)
|
- [delivery](API.delivery.md)
|
||||||
|
- `create(googleAuthId: number, body: object): Promise<{id: number, number: string, type: string, entityId: number, externalNumber: string|null, date: string, lines: Array<object>}>`
|
||||||
|
- `delete(googleAuthId: number, id: number): Promise<void>`
|
||||||
|
- `getById(googleAuthId: number, id: number): Promise<{id: number, number: string, type: string, entityId: number, externalNumber: string|null, date: string, lines: Array<object>}>`
|
||||||
|
- `list(googleAuthId: number): Promise<Array<{id: number, number: string, type: string, entityId: number, externalNumber: string|null, date: string}>>`
|
||||||
|
- `update(googleAuthId: number, id: number, patch: object): Promise<{id: number, number: string, type: string, entityId: number, externalNumber: string|null, date: string, lines: Array<object>}>`
|
||||||
- [quote](API.quote.md)
|
- [quote](API.quote.md)
|
||||||
|
- `create(googleAuthId: number, body: object): Promise<{id: number, number: string, type: string, entityId: number|null, externalNumber: string|null, date: string, lines: Array<object>}>`
|
||||||
|
- `delete(googleAuthId: number, id: number): Promise<void>`
|
||||||
|
- `getById(googleAuthId: number, id: number): Promise<{id: number, number: string, type: string, entityId: number|null, externalNumber: string|null, date: string, lines: Array<object>}>`
|
||||||
|
- `list(googleAuthId: number): Promise<Array<{id: number, number: string, type: string, entityId: number|null, externalNumber: string|null, date: string}>>`
|
||||||
|
- `update(googleAuthId: number, id: number, patch: object): Promise<{id: number, number: string, type: string, entityId: number|null, externalNumber: string|null, date: string, lines: Array<object>}>`
|
||||||
- [order](API.order.md)
|
- [order](API.order.md)
|
||||||
|
- `create(googleAuthId: number, body: object): Promise<{id: number, number: string, type: string, entityId: number|null, externalNumber: string|null, date: string, lines: Array<object>}>`
|
||||||
|
- `delete(googleAuthId: number, id: number): Promise<void>`
|
||||||
|
- `getById(googleAuthId: number, id: number): Promise<{id: number, number: string, type: string, entityId: number|null, externalNumber: string|null, date: string, lines: Array<object>}>`
|
||||||
|
- `list(googleAuthId: number): Promise<Array<{id: number, number: string, type: string, entityId: number|null, externalNumber: string|null, date: string}>>`
|
||||||
|
- `update(googleAuthId: number, id: number, patch: object): Promise<{id: number, number: string, type: string, entityId: number|null, externalNumber: string|null, date: string, lines: Array<object>}>`
|
||||||
|
- [manifestattachment](API.manifestattachment.md)
|
||||||
|
- `add(googleAuthId: number, manifestId: number, input: object): Promise<object>`
|
||||||
|
- `getById(googleAuthId: number, manifestId: number, id: number): Promise<object>`
|
||||||
|
- `listByManifestId(googleAuthId: number, manifestId: number): Promise<Array<object>>`
|
||||||
|
- `remove(googleAuthId: number, manifestId: number, id: number): Promise<void>`
|
||||||
- [posterminal](API.posterminal.md)
|
- [posterminal](API.posterminal.md)
|
||||||
|
- `delete(googleAuthId: number, id: number): Promise<void>`
|
||||||
|
- `list(googleAuthId: number): Promise<Array<{id: number, name: string, token: string, pairingpin: string}>>`
|
||||||
|
- `setOff(googleAuthId: number, posterminalId: number, categoryId: number): Promise<{id: number, categoryIds: Array<number>}>`
|
||||||
|
- `setOffAll(googleAuthId: number, posterminalId: number): Promise<{id: number, categoryIds: Array<number>}>`
|
||||||
|
- `setOn(googleAuthId: number, posterminalId: number, categoryId: number): Promise<{id: number, categoryIds: Array<number>}>`
|
||||||
|
- `setOnAll(googleAuthId: number, posterminalId: number): Promise<{id: number, categoryIds: Array<number>}>`
|
||||||
|
- `upsert(googleAuthId: number, input: object): Promise<{id: number, name: string, token: string, pairingpin: string}>`
|
||||||
- [google_auth](API.google_auth.md)
|
- [google_auth](API.google_auth.md)
|
||||||
|
- `add(email: string): Promise<number>`
|
||||||
|
- `getByEmail(email: string): Promise<object|undefined>`
|
||||||
|
- `getById(googleAuthId: number): Promise<object|undefined>`
|
||||||
|
- `listAllowedEmails(): Promise<Array<{id: number, email: string}>>`
|
||||||
|
- `removeAllowedEmail(email: string): Promise<void>`
|
||||||
|
- `setProfile(googleAuthId: number, input: object): Promise<void>`
|
||||||
|
- `setSelectedCompany(googleAuthId: number, companyId: number): Promise<void>`
|
||||||
- [pic](API.pic.md)
|
- [pic](API.pic.md)
|
||||||
|
- `getImageByHash(googleAuthId: number, fullHash: string): Promise<{buffer: Buffer, w: number, h: number, size: number, contentType: string}>`
|
||||||
|
- `getThumbByHash(googleAuthId: number, fullHash: string): Promise<{buffer: Buffer, w: number, h: number, contentType: string}>`
|
||||||
- [numbers](API.numbers.md)
|
- [numbers](API.numbers.md)
|
||||||
|
- `list(googleAuthId: number): Promise<Array<{id: number, type: string, prefix: string, padding: number, next: number}>>`
|
||||||
|
- `update(googleAuthId: number, id: number, input: object): Promise<{id: number, type: string, prefix: string, padding: number, next: number}>`
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ const MODULE_ORDER = [
|
|||||||
'delivery',
|
'delivery',
|
||||||
'quote',
|
'quote',
|
||||||
'order',
|
'order',
|
||||||
|
'manifestattachment',
|
||||||
'posterminal',
|
'posterminal',
|
||||||
'google_auth',
|
'google_auth',
|
||||||
'pic',
|
'pic',
|
||||||
@@ -51,6 +52,7 @@ const INTERNAL_FILES = new Set([
|
|||||||
'resolveEntityAccess.js',
|
'resolveEntityAccess.js',
|
||||||
'resolvePicAccess.js',
|
'resolvePicAccess.js',
|
||||||
'resolveArticleBySku.js',
|
'resolveArticleBySku.js',
|
||||||
|
'resolveManifestAccess.js',
|
||||||
'queryBySku.js',
|
'queryBySku.js',
|
||||||
'queryCategoryArticles.js',
|
'queryCategoryArticles.js',
|
||||||
'getCategoryPosterminalIds.js',
|
'getCategoryPosterminalIds.js',
|
||||||
@@ -193,6 +195,10 @@ function buildModules() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const entries of modules.values()) {
|
||||||
|
entries.sort((a, b) => a.name.localeCompare(b.name));
|
||||||
|
}
|
||||||
|
|
||||||
return modules;
|
return modules;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,6 +255,21 @@ function renderSection(moduleName, entries) {
|
|||||||
return lines.join('\n');
|
return lines.join('\n');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function formatMethodSignature(entry) {
|
||||||
|
const topLevelParams = (entry.params || []).filter((p) => !p.name.includes('.'));
|
||||||
|
const paramsStr = topLevelParams
|
||||||
|
.map((p) => {
|
||||||
|
const isOptional = p.name.startsWith('[');
|
||||||
|
const cleanName = p.name.replace(/^\[|\]$/g, '').split('=')[0].trim();
|
||||||
|
const typeStr = p.type ? `: ${p.type}` : '';
|
||||||
|
return `${cleanName}${isOptional ? '?' : ''}${typeStr}`;
|
||||||
|
})
|
||||||
|
.join(', ');
|
||||||
|
|
||||||
|
const returnType = entry.returns?.type ? `: ${entry.returns.type}` : ': void';
|
||||||
|
return `(${paramsStr})${returnType}`;
|
||||||
|
}
|
||||||
|
|
||||||
function render() {
|
function render() {
|
||||||
const modules = buildModules();
|
const modules = buildModules();
|
||||||
|
|
||||||
@@ -282,6 +303,11 @@ function render() {
|
|||||||
|
|
||||||
for (const { moduleName } of written) {
|
for (const { moduleName } of written) {
|
||||||
lines.push(`- [${moduleName}](API.${moduleName}.md)`);
|
lines.push(`- [${moduleName}](API.${moduleName}.md)`);
|
||||||
|
const entries = modules.get(moduleName) || [];
|
||||||
|
for (const entry of entries) {
|
||||||
|
const sig = formatMethodSignature(entry);
|
||||||
|
lines.push(` - \`${entry.name}${sig}\``);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
lines.push('');
|
lines.push('');
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ function parseSchema(source) {
|
|||||||
const trimmed = line.trim().replace(/,$/, '');
|
const trimmed = line.trim().replace(/,$/, '');
|
||||||
if (!trimmed || trimmed.startsWith('CONSTRAINT')) {
|
if (!trimmed || trimmed.startsWith('CONSTRAINT')) {
|
||||||
const fkMatch = trimmed.match(
|
const fkMatch = trimmed.match(
|
||||||
/CONSTRAINT\s+(\w+)\s+FOREIGN KEY\s*\(([^)]+)\)\s+REFERENCES\s+(\w+)\(([^)]+)\)(?:\s+ON DELETE\s+(.+))?/i
|
/CONSTRAINT\s+(\w+)\s+FOREIGN KEY\s*\(([^)]+)\)\s+REFERENCES\s+\[?(\w+)\]?\(([^)]+)\)(?:\s+ON DELETE\s+(.+))?/i
|
||||||
);
|
);
|
||||||
if (fkMatch) {
|
if (fkMatch) {
|
||||||
const constraintName = fkMatch[1];
|
const constraintName = fkMatch[1];
|
||||||
@@ -105,7 +105,7 @@ function parseSchema(source) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const alterFkRegex =
|
const alterFkRegex =
|
||||||
/ALTER TABLE\s+(\w+)\s+ADD CONSTRAINT\s+(\w+)\s+FOREIGN KEY\s*\(([^)]+)\)\s+REFERENCES\s+(\w+)\(([^)]+)\)(?:\s+ON DELETE\s+([\w\s]+?))?\s*;/gi;
|
/ALTER TABLE\s+(\w+)\s+ADD CONSTRAINT\s+(\w+)\s+FOREIGN KEY\s*\(([^)]+)\)\s+REFERENCES\s+\[?(\w+)\]?\(([^)]+)\)(?:\s+ON DELETE\s+([\w\s]+?))?\s*;/gi;
|
||||||
let alterMatch;
|
let alterMatch;
|
||||||
|
|
||||||
while ((alterMatch = alterFkRegex.exec(sqlBlock)) !== null) {
|
while ((alterMatch = alterFkRegex.exec(sqlBlock)) !== null) {
|
||||||
@@ -361,12 +361,12 @@ const CLUSTERS = [
|
|||||||
{
|
{
|
||||||
id: 'media',
|
id: 'media',
|
||||||
label: 'Media',
|
label: 'Media',
|
||||||
tables: ['pic', 'articlepic', 'categorypic', 'brandpic'],
|
tables: ['pic', 'articlepic', 'categorypic', 'brandpic', 'file'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'manifests',
|
id: 'manifests',
|
||||||
label: 'Documents',
|
label: 'Documents',
|
||||||
tables: ['manifest', 'manifestarticle', 'ledger'],
|
tables: ['manifest', 'manifestarticle', 'manifestattachment', 'ledger'],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'commerce',
|
id: 'commerce',
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
2698
schema-graph.svg
2698
schema-graph.svg
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 196 KiB After Width: | Height: | Size: 200 KiB |
11
src/index.js
11
src/index.js
@@ -110,6 +110,10 @@ import numbersList from './store/numbers/list.js';
|
|||||||
import numbersUpdate from './store/numbers/update.js';
|
import numbersUpdate from './store/numbers/update.js';
|
||||||
import storePurge from './store/purge.js';
|
import storePurge from './store/purge.js';
|
||||||
import storeInitialize from './store/initialize.js';
|
import storeInitialize from './store/initialize.js';
|
||||||
|
import manifestattachmentAdd from './store/manifestattachment/add.js';
|
||||||
|
import manifestattachmentRemove from './store/manifestattachment/remove.js';
|
||||||
|
import manifestattachmentListByManifestId from './store/manifestattachment/listByManifestId.js';
|
||||||
|
import manifestattachmentGetById from './store/manifestattachment/getById.js';
|
||||||
|
|
||||||
export default class LibDashStore {
|
export default class LibDashStore {
|
||||||
constructor(pool) {
|
constructor(pool) {
|
||||||
@@ -288,6 +292,13 @@ export default class LibDashStore {
|
|||||||
update: numbersUpdate(pool),
|
update: numbersUpdate(pool),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
this.manifestattachment = {
|
||||||
|
add: manifestattachmentAdd(pool),
|
||||||
|
remove: manifestattachmentRemove(pool),
|
||||||
|
listByManifestId: manifestattachmentListByManifestId(pool),
|
||||||
|
getById: manifestattachmentGetById(pool),
|
||||||
|
};
|
||||||
|
|
||||||
this.purge = storePurge(pool);
|
this.purge = storePurge(pool);
|
||||||
this.initialize = storeInitialize(pool);
|
this.initialize = storeInitialize(pool);
|
||||||
|
|
||||||
|
|||||||
@@ -765,6 +765,52 @@ BEGIN
|
|||||||
END
|
END
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
export const INIT_FILE = `
|
||||||
|
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'file')
|
||||||
|
BEGIN
|
||||||
|
CREATE TABLE [file] (
|
||||||
|
id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
mimetype NVARCHAR(255) NOT NULL,
|
||||||
|
name NVARCHAR(255) NOT NULL,
|
||||||
|
content VARBINARY(MAX) NOT NULL
|
||||||
|
);
|
||||||
|
END
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const INIT_MANIFESTATTACHMENT = `
|
||||||
|
IF NOT EXISTS (SELECT * FROM sys.tables WHERE name = 'manifestattachment')
|
||||||
|
BEGIN
|
||||||
|
CREATE TABLE manifestattachment (
|
||||||
|
id INT IDENTITY(1,1) PRIMARY KEY,
|
||||||
|
manifest_id INT NOT NULL,
|
||||||
|
file_id INT NOT NULL,
|
||||||
|
CONSTRAINT FK_manifestattachment_manifest FOREIGN KEY (manifest_id) REFERENCES manifest(id) ON DELETE CASCADE,
|
||||||
|
CONSTRAINT FK_manifestattachment_file FOREIGN KEY (file_id) REFERENCES [file](id) ON DELETE CASCADE
|
||||||
|
);
|
||||||
|
END
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const INIT_MANIFESTATTACHMENT_TRIGGER = `
|
||||||
|
IF OBJECT_ID(N'dbo.TR_manifestattachment_delete_file', N'TR') IS NOT NULL
|
||||||
|
DROP TRIGGER dbo.TR_manifestattachment_delete_file;
|
||||||
|
|
||||||
|
EXEC('
|
||||||
|
CREATE TRIGGER dbo.TR_manifestattachment_delete_file
|
||||||
|
ON manifestattachment
|
||||||
|
AFTER DELETE
|
||||||
|
AS
|
||||||
|
BEGIN
|
||||||
|
SET NOCOUNT ON;
|
||||||
|
DELETE f
|
||||||
|
FROM [file] f
|
||||||
|
INNER JOIN deleted d ON f.id = d.file_id
|
||||||
|
WHERE NOT EXISTS (
|
||||||
|
SELECT 1 FROM manifestattachment ma WHERE ma.file_id = f.id
|
||||||
|
);
|
||||||
|
END
|
||||||
|
');
|
||||||
|
`;
|
||||||
|
|
||||||
/** DDL scripts in dependency order for schema init. */
|
/** DDL scripts in dependency order for schema init. */
|
||||||
export const SCHEMA_SCRIPTS = [
|
export const SCHEMA_SCRIPTS = [
|
||||||
INIT_META,
|
INIT_META,
|
||||||
@@ -810,4 +856,8 @@ export const SCHEMA_SCRIPTS = [
|
|||||||
INIT_COMPANYSETTING,
|
INIT_COMPANYSETTING,
|
||||||
INIT_POSTERMINAL,
|
INIT_POSTERMINAL,
|
||||||
INIT_POSTERMINALCATEGORY,
|
INIT_POSTERMINALCATEGORY,
|
||||||
|
INIT_FILE,
|
||||||
|
INIT_MANIFESTATTACHMENT,
|
||||||
|
INIT_MANIFESTATTACHMENT_TRIGGER,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
62
src/sql/manifestattachment.js
Normal file
62
src/sql/manifestattachment.js
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
export const CHECK_MANIFEST_ACCESS = `
|
||||||
|
SELECT id, company_id AS companyId
|
||||||
|
FROM manifest
|
||||||
|
WHERE id = @manifestId AND company_id = @companyId
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const CREATE_FILE = `
|
||||||
|
INSERT INTO [file] (mimetype, name, content)
|
||||||
|
OUTPUT INSERTED.id
|
||||||
|
VALUES (@mimetype, @name, @content)
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const CREATE_ATTACHMENT = `
|
||||||
|
INSERT INTO manifestattachment (manifest_id, file_id)
|
||||||
|
OUTPUT INSERTED.id
|
||||||
|
VALUES (@manifestId, @fileId)
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const LIST_BY_MANIFEST = `
|
||||||
|
SELECT
|
||||||
|
ma.id,
|
||||||
|
ma.manifest_id AS manifestId,
|
||||||
|
ma.file_id AS fileId,
|
||||||
|
f.mimetype,
|
||||||
|
f.name,
|
||||||
|
DATALENGTH(f.content) AS size
|
||||||
|
FROM manifestattachment ma
|
||||||
|
INNER JOIN [file] f ON f.id = ma.file_id
|
||||||
|
WHERE ma.manifest_id = @manifestId
|
||||||
|
ORDER BY ma.id ASC
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const GET_BY_ID = `
|
||||||
|
SELECT
|
||||||
|
ma.id,
|
||||||
|
ma.manifest_id AS manifestId,
|
||||||
|
ma.file_id AS fileId,
|
||||||
|
f.mimetype,
|
||||||
|
f.name,
|
||||||
|
f.content
|
||||||
|
FROM manifestattachment ma
|
||||||
|
INNER JOIN [file] f ON f.id = ma.file_id
|
||||||
|
WHERE ma.manifest_id = @manifestId
|
||||||
|
AND (ma.id = @id OR ma.file_id = @id)
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const FIND_ATTACHMENT = `
|
||||||
|
SELECT ma.id, ma.file_id AS fileId
|
||||||
|
FROM manifestattachment ma
|
||||||
|
WHERE ma.manifest_id = @manifestId
|
||||||
|
AND (ma.id = @id OR ma.file_id = @id)
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const DELETE_ATTACHMENT = `
|
||||||
|
DELETE FROM manifestattachment
|
||||||
|
WHERE id = @id
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const DELETE_FILE = `
|
||||||
|
DELETE FROM [file]
|
||||||
|
WHERE id = @fileId
|
||||||
|
`;
|
||||||
99
src/store/manifestattachment/add.js
Normal file
99
src/store/manifestattachment/add.js
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
import { CREATE_FILE, CREATE_ATTACHMENT } from '../../sql/manifestattachment.js';
|
||||||
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
|
import resolveManifestAccess from './resolveManifestAccess.js';
|
||||||
|
import request from '../request.js';
|
||||||
|
|
||||||
|
export default function add(pool) {
|
||||||
|
const access = resolveSelectedCompanyAccess(pool);
|
||||||
|
const manifestAccess = resolveManifestAccess(pool);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attaches a file to an existing manifest.
|
||||||
|
*
|
||||||
|
* @param {number} googleAuthId - The id of the Google auth user.
|
||||||
|
* @param {number} manifestId - The id of the manifest.
|
||||||
|
* @param {object} input - The file data.
|
||||||
|
* @param {string} input.mimetype - The MIME type of the file (e.g. `'application/pdf'`).
|
||||||
|
* @param {string} input.name - The file name.
|
||||||
|
* @param {Buffer} input.content - The file content.
|
||||||
|
* @returns {Promise<object>} The created attachment record.
|
||||||
|
* @throws {Error} If the manifest is not found or file input is invalid.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const attachment = await store.manifestattachment.add(42, 1, {
|
||||||
|
* mimetype: 'application/pdf',
|
||||||
|
* name: 'invoice.pdf',
|
||||||
|
* content: fileBuffer,
|
||||||
|
* });
|
||||||
|
* // => { id, manifestId, fileId, mimetype, name }
|
||||||
|
*/
|
||||||
|
return async (googleAuthId, manifestId, input, ...rest) => {
|
||||||
|
let rawMimetype, rawName, rawContent;
|
||||||
|
if (typeof input === 'object' && input !== null && !Buffer.isBuffer(input)) {
|
||||||
|
rawMimetype = input.mimetype;
|
||||||
|
rawName = input.name;
|
||||||
|
rawContent = input.content;
|
||||||
|
} else {
|
||||||
|
rawMimetype = input;
|
||||||
|
rawName = rest[0];
|
||||||
|
rawContent = rest[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
const mimetype = typeof rawMimetype === 'string' ? rawMimetype.trim() : null;
|
||||||
|
if (!mimetype) {
|
||||||
|
throw new Error('Mimetype required');
|
||||||
|
}
|
||||||
|
|
||||||
|
const name = typeof rawName === 'string' ? rawName.trim() : null;
|
||||||
|
if (!name) {
|
||||||
|
throw new Error('File name required');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rawContent == null) {
|
||||||
|
throw new Error('Content required');
|
||||||
|
}
|
||||||
|
const content = Buffer.isBuffer(rawContent)
|
||||||
|
? rawContent
|
||||||
|
: Buffer.from(rawContent);
|
||||||
|
|
||||||
|
const { companyId } = await access(googleAuthId);
|
||||||
|
await manifestAccess(companyId, manifestId);
|
||||||
|
|
||||||
|
const tx = pool.transaction();
|
||||||
|
await tx.begin();
|
||||||
|
|
||||||
|
try {
|
||||||
|
const fileRes = await request(pool, tx)
|
||||||
|
.input('mimetype', mimetype)
|
||||||
|
.input('name', name)
|
||||||
|
.input('content', content)
|
||||||
|
.query(CREATE_FILE);
|
||||||
|
|
||||||
|
const fileId = fileRes.recordset[0].id;
|
||||||
|
|
||||||
|
const attachmentRes = await request(pool, tx)
|
||||||
|
.input('manifestId', manifestId)
|
||||||
|
.input('fileId', fileId)
|
||||||
|
.query(CREATE_ATTACHMENT);
|
||||||
|
|
||||||
|
const attachmentId = attachmentRes.recordset[0].id;
|
||||||
|
|
||||||
|
await tx.commit();
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: attachmentId,
|
||||||
|
manifestId,
|
||||||
|
fileId,
|
||||||
|
mimetype,
|
||||||
|
name,
|
||||||
|
};
|
||||||
|
} catch (err) {
|
||||||
|
try {
|
||||||
|
await tx.rollback();
|
||||||
|
} catch {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
50
src/store/manifestattachment/getById.js
Normal file
50
src/store/manifestattachment/getById.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import { GET_BY_ID } from '../../sql/manifestattachment.js';
|
||||||
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
|
import resolveManifestAccess from './resolveManifestAccess.js';
|
||||||
|
import request from '../request.js';
|
||||||
|
|
||||||
|
export default function getById(pool) {
|
||||||
|
const access = resolveSelectedCompanyAccess(pool);
|
||||||
|
const manifestAccess = resolveManifestAccess(pool);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets an attachment for a manifest by its attachment ID or file ID, including full file content.
|
||||||
|
*
|
||||||
|
* @param {number} googleAuthId - The id of the Google auth user.
|
||||||
|
* @param {number} manifestId - The manifest ID.
|
||||||
|
* @param {number} id - The attachment ID or file ID.
|
||||||
|
* @returns {Promise<object>} The attachment record with binary content.
|
||||||
|
* @throws {Error} If the manifest or attachment is not found, or user is not authorized.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const attachment = await store.manifestattachment.getById(42, 1, 5);
|
||||||
|
* // => { id, manifestId, fileId, mimetype, name, content }
|
||||||
|
*/
|
||||||
|
return async (googleAuthId, manifestId, id) => {
|
||||||
|
if (!Number.isFinite(id)) {
|
||||||
|
throw new Error('Attachment not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { companyId } = await access(googleAuthId);
|
||||||
|
await manifestAccess(companyId, manifestId);
|
||||||
|
|
||||||
|
const res = await request(pool)
|
||||||
|
.input('manifestId', manifestId)
|
||||||
|
.input('id', id)
|
||||||
|
.query(GET_BY_ID);
|
||||||
|
|
||||||
|
const row = res.recordset[0];
|
||||||
|
if (!row) {
|
||||||
|
throw new Error('Attachment not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
id: row.id,
|
||||||
|
manifestId: row.manifestId,
|
||||||
|
fileId: row.fileId,
|
||||||
|
mimetype: row.mimetype,
|
||||||
|
name: row.name,
|
||||||
|
content: row.content,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
43
src/store/manifestattachment/listByManifestId.js
Normal file
43
src/store/manifestattachment/listByManifestId.js
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import { LIST_BY_MANIFEST } from '../../sql/manifestattachment.js';
|
||||||
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
|
import resolveManifestAccess from './resolveManifestAccess.js';
|
||||||
|
import request from '../request.js';
|
||||||
|
|
||||||
|
function shape(row) {
|
||||||
|
return {
|
||||||
|
id: row.id,
|
||||||
|
manifestId: row.manifestId,
|
||||||
|
fileId: row.fileId,
|
||||||
|
mimetype: row.mimetype,
|
||||||
|
name: row.name,
|
||||||
|
size: row.size,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function listByManifestId(pool) {
|
||||||
|
const access = resolveSelectedCompanyAccess(pool);
|
||||||
|
const manifestAccess = resolveManifestAccess(pool);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Lists all attachments for a given manifest, without loading their full binary content.
|
||||||
|
*
|
||||||
|
* @param {number} googleAuthId - The id of the Google auth user.
|
||||||
|
* @param {number} manifestId - The manifest ID.
|
||||||
|
* @returns {Promise<Array<object>>} A list of attachment metadata objects.
|
||||||
|
* @throws {Error} If the manifest is not found or the user is not authorized.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* const attachments = await store.manifestattachment.listByManifestId(42, 1);
|
||||||
|
* // => [{ id, manifestId, fileId, mimetype, name, size }]
|
||||||
|
*/
|
||||||
|
return async (googleAuthId, manifestId) => {
|
||||||
|
const { companyId } = await access(googleAuthId);
|
||||||
|
await manifestAccess(companyId, manifestId);
|
||||||
|
|
||||||
|
const res = await request(pool)
|
||||||
|
.input('manifestId', manifestId)
|
||||||
|
.query(LIST_BY_MANIFEST);
|
||||||
|
|
||||||
|
return res.recordset.map(shape);
|
||||||
|
};
|
||||||
|
}
|
||||||
44
src/store/manifestattachment/remove.js
Normal file
44
src/store/manifestattachment/remove.js
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
import { FIND_ATTACHMENT, DELETE_FILE } from '../../sql/manifestattachment.js';
|
||||||
|
import resolveSelectedCompanyAccess from '../companyuser/resolveSelectedCompanyAccess.js';
|
||||||
|
import resolveManifestAccess from './resolveManifestAccess.js';
|
||||||
|
import request from '../request.js';
|
||||||
|
|
||||||
|
export default function remove(pool) {
|
||||||
|
const access = resolveSelectedCompanyAccess(pool);
|
||||||
|
const manifestAccess = resolveManifestAccess(pool);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a file attachment from a manifest and deletes the underlying file.
|
||||||
|
*
|
||||||
|
* @param {number} googleAuthId - The id of the Google auth user.
|
||||||
|
* @param {number} manifestId - The manifest ID.
|
||||||
|
* @param {number} id - The attachment ID or file ID to remove.
|
||||||
|
* @returns {Promise<void>}
|
||||||
|
* @throws {Error} If the manifest or attachment is not found, or user is not authorized.
|
||||||
|
*
|
||||||
|
* @example
|
||||||
|
* await store.manifestattachment.remove(42, 1, 5);
|
||||||
|
*/
|
||||||
|
return async (googleAuthId, manifestId, id) => {
|
||||||
|
if (!Number.isFinite(id)) {
|
||||||
|
throw new Error('Attachment not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const { companyId } = await access(googleAuthId);
|
||||||
|
await manifestAccess(companyId, manifestId);
|
||||||
|
|
||||||
|
const findRes = await request(pool)
|
||||||
|
.input('manifestId', manifestId)
|
||||||
|
.input('id', id)
|
||||||
|
.query(FIND_ATTACHMENT);
|
||||||
|
|
||||||
|
const row = findRes.recordset[0];
|
||||||
|
if (!row) {
|
||||||
|
throw new Error('Attachment not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
await request(pool)
|
||||||
|
.input('fileId', row.fileId)
|
||||||
|
.query(DELETE_FILE);
|
||||||
|
};
|
||||||
|
}
|
||||||
22
src/store/manifestattachment/resolveManifestAccess.js
Normal file
22
src/store/manifestattachment/resolveManifestAccess.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
import { CHECK_MANIFEST_ACCESS } from '../../sql/manifestattachment.js';
|
||||||
|
import request from '../request.js';
|
||||||
|
|
||||||
|
/** Ensure manifest belongs to company. Throws Manifest not found. */
|
||||||
|
export default function resolveManifestAccess(pool) {
|
||||||
|
return async (companyId, manifestId, tx) => {
|
||||||
|
if (!Number.isFinite(manifestId)) {
|
||||||
|
throw new Error('Manifest not found');
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await request(pool, tx)
|
||||||
|
.input('manifestId', manifestId)
|
||||||
|
.input('companyId', companyId)
|
||||||
|
.query(CHECK_MANIFEST_ACCESS);
|
||||||
|
|
||||||
|
const row = result.recordset[0];
|
||||||
|
if (!row) {
|
||||||
|
throw new Error('Manifest not found');
|
||||||
|
}
|
||||||
|
return row;
|
||||||
|
};
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user