u
This commit is contained in:
@@ -209,22 +209,26 @@ Returns the change history of an article by its SKU.
|
|||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `googleAuthId` | `number` | The id of the Google auth user. |
|
| `googleAuthId` | `number` | The id of the Google auth user. |
|
||||||
| `sku` | `string` | The article SKU. |
|
| `sku` | `string` | The article SKU. |
|
||||||
| `[opts]` | `object` | Optional options. |
|
| `[opts]` | `object` | Optional pagination and filter options. |
|
||||||
| `[opts.limit]` | `number` | Maximum number of entries to return (newest first). |
|
| `[opts.offset=0]` | `number` | Number of entries to skip. |
|
||||||
|
| `[opts.limit=50]` | `number` | Number of entries to return. |
|
||||||
|
| `[opts.search]` | `string` | Optional search filter for history text. |
|
||||||
|
| `[opts.seekMonths]` | `number` | Negative integer cutoff months ago. |
|
||||||
|
| `[opts.paged]` | `boolean` | Explicitly return paged result object. |
|
||||||
| `[tx]` | `object` | Optional transaction. |
|
| `[tx]` | `object` | Optional transaction. |
|
||||||
|
|
||||||
**Returns**
|
**Returns**
|
||||||
|
|
||||||
`Promise<Array<{id: number, companyuserId: number|null, date: string, text: string, meta: string|null}>>` — The article history entries.
|
`Promise<{history: Array<{id: number, companyuserId: number|null, date: string, text: string, meta: string|null}>, total: number, unfilteredTotal: number, offset: number, limit: number}|Array<{id: number, companyuserId: number|null, date: string, text: string, meta: string|null}>>` — The article history entries.
|
||||||
|
|
||||||
**Example**
|
**Example**
|
||||||
|
|
||||||
```js
|
```js
|
||||||
|
const result = await store.article.getHistoryBySku(42, 'SKU-1', { offset: 0, limit: 50, search: 'Tee' });
|
||||||
|
// => { history: [...], total, unfilteredTotal, offset, limit }
|
||||||
|
|
||||||
const history = await store.article.getHistoryBySku(42, 'SKU-1');
|
const history = await store.article.getHistoryBySku(42, 'SKU-1');
|
||||||
// => [{ id, companyuserId, date, text, meta }]
|
// => [{ id, companyuserId, date, text, meta }]
|
||||||
|
|
||||||
const recent = await store.article.getHistoryBySku(42, 'SKU-1', { limit: 5 });
|
|
||||||
// => up to 5 most recent entries
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## `article.importRows`
|
## `article.importRows`
|
||||||
|
|||||||
2
API.md
2
API.md
@@ -112,7 +112,7 @@ The store is exposed as a `LibDashStore` instance (see `src/index.js`). Each met
|
|||||||
- `delete(googleAuthId: number, sku: string, optionsOrTx?: object|*, maybeTx?: object): Promise<void>`
|
- `delete(googleAuthId: number, sku: string, optionsOrTx?: object|*, maybeTx?: object): Promise<void>`
|
||||||
- `deleteImage(googleAuthId: number, sku: string, fullHash: string, tx?: object): Promise<void>`
|
- `deleteImage(googleAuthId: number, sku: string, fullHash: string, tx?: object): Promise<void>`
|
||||||
- `getBySku(googleAuthId: number): Promise<{article: {id: number, sku: string, name: string, slug: string, desc: string|null, seo: string|null, unitamount: number|null, weight: number|null, track_stock: boolean, unit: {si: string|null, basesi: string|null, basesifactor: number|null, symbol: string|null, name: string|null}, brand: {id: number|null, name: string, fullHash: string|null, thumbW: number|null, thumbH: number|null, thumbHash: string|null}|null, categoryIds: number[], photos: Array<{sort: number, fullHash: string, fullW: number, fullH: number, fullSize: number, thumbW: number, thumbH: number, thumbHash: string}>, eans: string[], prices: Array<{minmultiplier: number, net: number, taxRate: number, customergroupId: number}>, suppliers: Array<{id: number, articleId: number, entityId: number, supplierName: string|null, sku: string|null, pu: number, stock: number|null, sort: number, price: {net: number, taxId: number, taxRate?: number}|null, incoming: Array<{date: string, amount: number}>}>, warehouses: Array<{id: number, name: string, sort: number, stock: number}>, undeliveredOrders: Array<{orderId: number, orderNumber: string, date: string, customerName: string|null, amount: number}>, optionsCount: number, articleListCount: number, childCount: number, parentArticleId: number|null, parentSku: string|null}}>`
|
- `getBySku(googleAuthId: number): Promise<{article: {id: number, sku: string, name: string, slug: string, desc: string|null, seo: string|null, unitamount: number|null, weight: number|null, track_stock: boolean, unit: {si: string|null, basesi: string|null, basesifactor: number|null, symbol: string|null, name: string|null}, brand: {id: number|null, name: string, fullHash: string|null, thumbW: number|null, thumbH: number|null, thumbHash: string|null}|null, categoryIds: number[], photos: Array<{sort: number, fullHash: string, fullW: number, fullH: number, fullSize: number, thumbW: number, thumbH: number, thumbHash: string}>, eans: string[], prices: Array<{minmultiplier: number, net: number, taxRate: number, customergroupId: number}>, suppliers: Array<{id: number, articleId: number, entityId: number, supplierName: string|null, sku: string|null, pu: number, stock: number|null, sort: number, price: {net: number, taxId: number, taxRate?: number}|null, incoming: Array<{date: string, amount: number}>}>, warehouses: Array<{id: number, name: string, sort: number, stock: number}>, undeliveredOrders: Array<{orderId: number, orderNumber: string, date: string, customerName: string|null, amount: number}>, optionsCount: number, articleListCount: number, childCount: number, parentArticleId: number|null, parentSku: string|null}}>`
|
||||||
- `getHistoryBySku(googleAuthId: number, sku: string, opts?: {limit?: number}, tx?: object): Promise<Array<{id: number, companyuserId: number|null, date: string, text: string, meta: string|null}>>`
|
- `getHistoryBySku(googleAuthId: number, sku: string, opts?: {offset?: number, limit?: number, search?: string, seekMonths?: number, paged?: boolean}, tx?: object): Promise<{history: Array<{id: number, companyuserId: number|null, date: string, text: string, meta: string|null}>, total: number, unfilteredTotal: number, offset: number, limit: number}|Array<{id: number, companyuserId: number|null, date: string, text: string, meta: string|null}>>`
|
||||||
- `importRows(input: {googleAuthId: number, rows: Array<object>}, tx?: object): Promise<{imported: Array<object>, skipped: Array<object>, errors: Array<object>}>`
|
- `importRows(input: {googleAuthId: number, rows: Array<object>}, tx?: object): Promise<{imported: Array<object>, skipped: Array<object>, errors: Array<object>}>`
|
||||||
- `listChildren(googleAuthId: number, parentSku: string, tx?: object): Promise<Array<{id: number, sku: string, parentsort: number, trackStock: boolean, unitamount: number, weight: number, name: string|null, slug: string|null, attributeValueId: number|null, attributeValue: string|null}>>`
|
- `listChildren(googleAuthId: number, parentSku: string, tx?: object): Promise<Array<{id: number, sku: string, parentsort: number, trackStock: boolean, unitamount: number, weight: number, name: string|null, slug: string|null, attributeValueId: number|null, attributeValue: string|null}>>`
|
||||||
- `listExport(googleAuthId: number, categoryId?: number|null, tx?: object): Promise<Array<object>>`
|
- `listExport(googleAuthId: number, categoryId?: number|null, tx?: object): Promise<Array<object>>`
|
||||||
|
|||||||
162
package-lock.json
generated
162
package-lock.json
generated
@@ -15,7 +15,7 @@
|
|||||||
"dotenv": "^18.0.8",
|
"dotenv": "^18.0.8",
|
||||||
"pdfconvert-wasm": "^0.3.0",
|
"pdfconvert-wasm": "^0.3.0",
|
||||||
"sharp": "^0.35.5",
|
"sharp": "^0.35.5",
|
||||||
"skelehash-wasm": "^0.1.0",
|
"skelehash-wasm": "file:../skelehash-wasm",
|
||||||
"thumbhash": "^0.1.1"
|
"thumbhash": "^0.1.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@@ -32,6 +32,13 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"../skelehash-wasm": {
|
||||||
|
"version": "0.1.0",
|
||||||
|
"license": "MIT",
|
||||||
|
"devDependencies": {
|
||||||
|
"sharp": "^0.35.5"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@azure-rest/core-client": {
|
"node_modules/@azure-rest/core-client": {
|
||||||
"version": "2.9.0",
|
"version": "2.9.0",
|
||||||
"resolved": "https://registry.npmjs.org/@azure-rest/core-client/-/core-client-2.9.0.tgz",
|
"resolved": "https://registry.npmjs.org/@azure-rest/core-client/-/core-client-2.9.0.tgz",
|
||||||
@@ -184,9 +191,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@azure/identity": {
|
"node_modules/@azure/identity": {
|
||||||
"version": "4.13.3",
|
"version": "4.14.0",
|
||||||
"resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.13.3.tgz",
|
"resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.14.0.tgz",
|
||||||
"integrity": "sha512-zGQPtqvXPgSA8yfV2CkIQ1qirqk0p9AIVpC5uEkdXQYcKl07QHvyaGYRnZOk0AsQUmxNb4wfkcwY5di8Z5xa9A==",
|
"integrity": "sha512-8utCLdTZn14CiAe0HW4JbtzUMsc0mdDwnjUvStFMrR4IxQP8S2eL9zVAdplpfORVJGYmidZElpeXRYjJQ4UyUw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -200,7 +207,7 @@
|
|||||||
"@azure/logger": "^1.0.0",
|
"@azure/logger": "^1.0.0",
|
||||||
"@azure/msal-browser": "^5.5.0",
|
"@azure/msal-browser": "^5.5.0",
|
||||||
"@azure/msal-node": "^6.0.0",
|
"@azure/msal-node": "^6.0.0",
|
||||||
"open": "^10.1.0",
|
"open": "^11.0.0",
|
||||||
"tslib": "^2.2.0"
|
"tslib": "^2.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -265,22 +272,22 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@azure/msal-browser": {
|
"node_modules/@azure/msal-browser": {
|
||||||
"version": "5.22.0",
|
"version": "5.26.0",
|
||||||
"resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-5.22.0.tgz",
|
"resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-5.26.0.tgz",
|
||||||
"integrity": "sha512-5kgu9xeEKgGc2JeidxAtU15NJTqiH/CMCRRQAJ4Rac56kB7KVg91vbNmn+z3RO1vNomPN69UvjKG9h1Pghx6dQ==",
|
"integrity": "sha512-GYKRquzDZmZggCdStWy2bNJKnPui1upssSuznJgP+/h6Mb0ldkUkaGvaY6uSGGmZOm0CGiBQ3b5BiGy43BpXSg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@azure/msal-common": "16.14.1"
|
"@azure/msal-common": "16.14.3"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.8.0"
|
"node": ">=0.8.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@azure/msal-common": {
|
"node_modules/@azure/msal-common": {
|
||||||
"version": "16.14.1",
|
"version": "16.14.3",
|
||||||
"resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-16.14.1.tgz",
|
"resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-16.14.3.tgz",
|
||||||
"integrity": "sha512-Or6xhPNyi4zHW25158yxBoyxuCqNSPa5YBVqfF1J5Ks4MJWBo/USXdp05DQIPu1Zli00YZu6t0+h6KvHJealxQ==",
|
"integrity": "sha512-tz3GvMrR9V/plb2lDdW8qaO8CPpfZevdExBKjltzzbAtyhK0eB2UIvji1aU+gkyHj3fxQ2ie+LNHyMXdmo8wOg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
@@ -301,6 +308,16 @@
|
|||||||
"node": ">=20"
|
"node": ">=20"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@azure/msal-node/node_modules/@azure/msal-common": {
|
||||||
|
"version": "16.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-16.14.1.tgz",
|
||||||
|
"integrity": "sha512-Or6xhPNyi4zHW25158yxBoyxuCqNSPa5YBVqfF1J5Ks4MJWBo/USXdp05DQIPu1Zli00YZu6t0+h6KvHJealxQ==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.8.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@clack/core": {
|
"node_modules/@clack/core": {
|
||||||
"version": "1.5.1",
|
"version": "1.5.1",
|
||||||
"resolved": "https://registry.npmjs.org/@clack/core/-/core-1.5.1.tgz",
|
"resolved": "https://registry.npmjs.org/@clack/core/-/core-1.5.1.tgz",
|
||||||
@@ -340,9 +357,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@hpcc-js/wasm-graphviz": {
|
"node_modules/@hpcc-js/wasm-graphviz": {
|
||||||
"version": "1.29.2",
|
"version": "1.30.0",
|
||||||
"resolved": "https://registry.npmjs.org/@hpcc-js/wasm-graphviz/-/wasm-graphviz-1.29.2.tgz",
|
"resolved": "https://registry.npmjs.org/@hpcc-js/wasm-graphviz/-/wasm-graphviz-1.30.0.tgz",
|
||||||
"integrity": "sha512-AkArBAZERT5OxH52/+kvCHB07cZ6ZNd9GnOvjw+S880bR88D6i27XfK6xj4dBhUDxNA2QPPMdgEcky3x4TJ3KA==",
|
"integrity": "sha512-T20IKosOZuex2qV049fQokVJy2MWv8w9Md5V/4mRKCXDf49fBCR50VD1yBlPYHaQlHPsFGRdqXN//r59vZliWQ==",
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/@img/colour": {
|
"node_modules/@img/colour": {
|
||||||
@@ -894,9 +911,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@js-joda/core": {
|
"node_modules/@js-joda/core": {
|
||||||
"version": "6.1.0",
|
"version": "6.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/@js-joda/core/-/core-6.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/@js-joda/core/-/core-6.3.0.tgz",
|
||||||
"integrity": "sha512-H8NTMRDJqad/leyv/D/A3kSOsf5/58Ydj4DJGDyaCWk9OU/zuZOLhndVffJgQjsgrn5GC0znHMHie7TfvPPG4w==",
|
"integrity": "sha512-mdmjc6lJkTCORsHlMxBT9XM1yLqgtsNZmv/Hwme2v/HIb15D2XcmklZKTnynqBgsSizA9SkFvzpuksfIXhDV/w==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "BSD-3-Clause"
|
"license": "BSD-3-Clause"
|
||||||
},
|
},
|
||||||
@@ -908,9 +925,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/node": {
|
"node_modules/@types/node": {
|
||||||
"version": "26.6.2",
|
"version": "26.6.5",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.2.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.5.tgz",
|
||||||
"integrity": "sha512-X1P21scMv4zGKLYqjdGjaKa7COa0RKVYYZZN/NfvLQ1JegxFhdhpZG/Lyn8AXx6CDUavKAd11v6BvfpkDByK8g==",
|
"integrity": "sha512-uMzsv9stDdofIZBx4UGh4Z9ZgXnGC9seRDscilBcTHAeOFk67MZg/k9bWVfO+bk4qZmG+l52hRnLwUiH2LnJTg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -918,9 +935,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@types/readable-stream": {
|
"node_modules/@types/readable-stream": {
|
||||||
"version": "4.0.24",
|
"version": "4.0.25",
|
||||||
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.24.tgz",
|
"resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.25.tgz",
|
||||||
"integrity": "sha512-NRvUNC/JFGPJvqdAfEve8oginbM6V08u5NzLWpG8MwA2kTPOLnqk+wpwuPT+mp3aUsxyuT6m2gnrPuHYCruzEg==",
|
"integrity": "sha512-7GsxL8Wd5X3jh73/qgW7WCnbBvGSdD8U3E4Jiuus3/8I+PN20DtlkJtwFhr/sImXfDDQ2Z03i/9wNiIF3TVSsw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1045,9 +1062,9 @@
|
|||||||
"license": "BSD-3-Clause"
|
"license": "BSD-3-Clause"
|
||||||
},
|
},
|
||||||
"node_modules/bundle-name": {
|
"node_modules/bundle-name": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.1.tgz",
|
||||||
"integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==",
|
"integrity": "sha512-DdH81/zPLVS11EUgWq3tEu/xn+EzljlMYooDNdzWEnFha3R3NBMpMV1UqYIpjYHV/SgpFKMIX1Oh7o06SjM/oA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1153,9 +1170,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/dotenv": {
|
"node_modules/dotenv": {
|
||||||
"version": "18.0.8",
|
"version": "18.0.9",
|
||||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-18.0.8.tgz",
|
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-18.0.9.tgz",
|
||||||
"integrity": "sha512-2KDeoFoK/zRtcnbunCDlLG5VWVMcyqeQc6iK65o231nfNAcuGrKoqUQfJFUtBI+QlShk5HKIHxwebBtUl3rEfA==",
|
"integrity": "sha512-3fVOW4cB02R066PUSwn8O4TJyz9NckQl7F81blIbaq9jKBm2tSmOKky7ZHIXzGvkVPXCSn6jkpziBPZdGFs8Tw==",
|
||||||
"license": "BSD-2-Clause",
|
"license": "BSD-2-Clause",
|
||||||
"bin": {
|
"bin": {
|
||||||
"dotenv": "dist/index.cjs"
|
"dotenv": "dist/index.cjs"
|
||||||
@@ -1310,6 +1327,19 @@
|
|||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/is-in-ssh": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-in-ssh/-/is-in-ssh-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/is-inside-container": {
|
"node_modules/is-inside-container": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
|
||||||
@@ -1455,9 +1485,9 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/mssql": {
|
"node_modules/mssql": {
|
||||||
"version": "12.7.9",
|
"version": "12.7.11",
|
||||||
"resolved": "https://registry.npmjs.org/mssql/-/mssql-12.7.9.tgz",
|
"resolved": "https://registry.npmjs.org/mssql/-/mssql-12.7.11.tgz",
|
||||||
"integrity": "sha512-ryuy8HyUpsUgg16mkjNumuGK0/kzZ9TNkKSm/lfNcb8v5RII/U4ErOquH/kAvUqXbap9BWV0EnN5JxdewGrx7g==",
|
"integrity": "sha512-O24UQA++JLvMUy5T6xL73kCHP4YjLMS6DBxKFeiWyc9kZW2mrVAZ6uqly2d3hGtBTXHRFRImfM+3EdCZVE5bWQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1492,19 +1522,21 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/open": {
|
"node_modules/open": {
|
||||||
"version": "10.2.0",
|
"version": "11.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/open/-/open-10.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/open/-/open-11.0.4.tgz",
|
||||||
"integrity": "sha512-YgBpdJHPyQ2UE5x+hlSXcnejzAvD0b22U2OuAP+8OnlJT+PjWPxtgmGqKKc+RgTM63U9gN0YzrYc71R2WT/hTA==",
|
"integrity": "sha512-++Zlftm0kVLPmzC06t6epuWmcRMDbI4z5P3NNX979WA/k23+NtSOynEGzsVfZwguKw2mi5umVgnBlJQMwRz4Pg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"default-browser": "^5.2.1",
|
"default-browser": "^5.5.1",
|
||||||
"define-lazy-prop": "^3.0.0",
|
"define-lazy-prop": "^3.0.0",
|
||||||
|
"is-in-ssh": "^1.0.0",
|
||||||
"is-inside-container": "^1.0.0",
|
"is-inside-container": "^1.0.0",
|
||||||
"wsl-utils": "^0.1.0"
|
"powershell-utils": "^0.2.1",
|
||||||
|
"wsl-utils": "^1.0.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=20"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
@@ -1516,6 +1548,19 @@
|
|||||||
"integrity": "sha512-FbEk+Grg0UST4kOPuN7OFfVsut1FvDOJNPS3pt4rzCS8VlFsFzD7ptg7YtFZjEOKgJ4MgqlfCgjK4RYaRBpT0Q==",
|
"integrity": "sha512-FbEk+Grg0UST4kOPuN7OFfVsut1FvDOJNPS3pt4rzCS8VlFsFzD7ptg7YtFZjEOKgJ4MgqlfCgjK4RYaRBpT0Q==",
|
||||||
"license": "GPLv3"
|
"license": "GPLv3"
|
||||||
},
|
},
|
||||||
|
"node_modules/powershell-utils": {
|
||||||
|
"version": "0.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.2.1.tgz",
|
||||||
|
"integrity": "sha512-C+y9x90UElAddDZmV4qOx9W53B61PO7cIqWz2dQsWlwswuq4mr8NEwytdGKboYbQlGZ3awrkTeNvcZiZNHnQ8A==",
|
||||||
|
"dev": true,
|
||||||
|
"license": "MIT",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=20"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/process": {
|
"node_modules/process": {
|
||||||
"version": "0.11.10",
|
"version": "0.11.10",
|
||||||
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
"resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
|
||||||
@@ -1527,9 +1572,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/readable-stream": {
|
"node_modules/readable-stream": {
|
||||||
"version": "4.7.0",
|
"version": "4.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.8.0.tgz",
|
||||||
"integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==",
|
"integrity": "sha512-2jhTTU3Eilp/2DMT71gbcoqC35eQHasMJH0RHkYxwlxIv3+FR6Y5xAFZIwEGLxKkjZYEFlsiMNIdwUqjK2lLHQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1652,17 +1697,8 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/skelehash-wasm": {
|
"node_modules/skelehash-wasm": {
|
||||||
"version": "0.1.0",
|
"resolved": "../skelehash-wasm",
|
||||||
"resolved": "https://registry.npmjs.org/skelehash-wasm/-/skelehash-wasm-0.1.0.tgz",
|
"link": true
|
||||||
"integrity": "sha512-QdxF9YsJvKlT93O70dXFaWnsKVX7KDD0RgYf9cwgOT6kGnSMOdsO0rsdge+5Tg+vv6BjivbJ/2o5P1KcQsavEw==",
|
|
||||||
"license": "MIT"
|
|
||||||
},
|
|
||||||
"node_modules/sprintf-js": {
|
|
||||||
"version": "1.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz",
|
|
||||||
"integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==",
|
|
||||||
"dev": true,
|
|
||||||
"license": "BSD-3-Clause"
|
|
||||||
},
|
},
|
||||||
"node_modules/string_decoder": {
|
"node_modules/string_decoder": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.0",
|
||||||
@@ -1685,9 +1721,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/tedious": {
|
"node_modules/tedious": {
|
||||||
"version": "20.0.0",
|
"version": "20.3.8",
|
||||||
"resolved": "https://registry.npmjs.org/tedious/-/tedious-20.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/tedious/-/tedious-20.3.8.tgz",
|
||||||
"integrity": "sha512-bTR0aou0Ghucf0ytvZUJjnKHGKDV8tT57jPYtEkSpfTWFe++4uR1wxJLQ4mh5wlSvAYXzmgBxbI0vaE56qigXw==",
|
"integrity": "sha512-ZrJiwyGn340Sa0V0g37Xqj5bvmJ1riYwvEtg7zdm/lpw70f2ZNIQ2fvHmntU5fEOorWDa48Jo1oKYAuUP+rh7Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
@@ -1699,8 +1735,7 @@
|
|||||||
"bl": "^6.1.4",
|
"bl": "^6.1.4",
|
||||||
"iconv-lite": "^0.7.0",
|
"iconv-lite": "^0.7.0",
|
||||||
"js-md4": "^0.3.2",
|
"js-md4": "^0.3.2",
|
||||||
"native-duplexpair": "^1.0.0",
|
"native-duplexpair": "^1.0.0"
|
||||||
"sprintf-js": "^1.1.3"
|
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=22"
|
"node": ">=22"
|
||||||
@@ -1727,16 +1762,17 @@
|
|||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/wsl-utils": {
|
"node_modules/wsl-utils": {
|
||||||
"version": "0.1.0",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-1.0.1.tgz",
|
||||||
"integrity": "sha512-h3Fbisa2nKGPxCpm89Hk33lBLsnaGBvctQopaBSOW/uIs6FTe1ATyAnKFJrzVs9vpGdsTe73WF3V4lIsk4Gacw==",
|
"integrity": "sha512-c16PKLIRxBYpR3jSWsdS7SFp0COm5SOQdiFjY818dYFHJbMGuLBszpF07LBWmOS1uzrHa9VGdynsEgoeKy0oOQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"is-wsl": "^3.1.0"
|
"is-wsl": "^3.1.0",
|
||||||
|
"powershell-utils": "^0.2.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=18"
|
"node": ">=20"
|
||||||
},
|
},
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
"dotenv": "^18.0.8",
|
"dotenv": "^18.0.8",
|
||||||
"pdfconvert-wasm": "^0.3.0",
|
"pdfconvert-wasm": "^0.3.0",
|
||||||
"sharp": "^0.35.5",
|
"sharp": "^0.35.5",
|
||||||
"skelehash-wasm": "^0.1.0",
|
"skelehash-wasm": "file:../skelehash-wasm",
|
||||||
"thumbhash": "^0.1.1"
|
"thumbhash": "^0.1.1"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
@@ -47,4 +47,4 @@
|
|||||||
"better-sqlite3": "^13.0.3",
|
"better-sqlite3": "^13.0.3",
|
||||||
"mssql": "^12.7.9"
|
"mssql": "^12.7.9"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,37 +1,64 @@
|
|||||||
import { LIST_BY_ARTICLE_ID as MSSQL_QUERY, LIST_BY_ARTICLE_ID_LIMITED as MSSQL_QUERY_LIMITED } from '../../providers/mssql/queries/articlehistory.js';
|
|
||||||
import { LIST_BY_ARTICLE_ID as SQLITE_QUERY, LIST_BY_ARTICLE_ID_LIMITED as SQLITE_QUERY_LIMITED } from '../../providers/sqlite3/queries/articlehistory.js';
|
|
||||||
import resolveArticleBySku from './resolveArticleBySku.js';
|
import resolveArticleBySku from './resolveArticleBySku.js';
|
||||||
import makeRunner from '../runner.js';
|
import makeRunner from '../runner.js';
|
||||||
|
|
||||||
export default function getHistoryBySku(provider) {
|
export default function getHistoryBySku(provider) {
|
||||||
const resolve = resolveArticleBySku(provider);
|
const resolve = resolveArticleBySku(provider);
|
||||||
const isSqlite = provider?.dialect === 'sqlite3';
|
const isSqlite = provider?.dialect === 'sqlite3';
|
||||||
const sql = isSqlite ? SQLITE_QUERY : MSSQL_QUERY;
|
|
||||||
const sqlLimited = isSqlite ? SQLITE_QUERY_LIMITED : MSSQL_QUERY_LIMITED;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the change history of an article by its SKU.
|
* Returns the change history of an article by its SKU.
|
||||||
*
|
*
|
||||||
* @param {number} googleAuthId - The id of the Google auth user.
|
* @param {number} googleAuthId - The id of the Google auth user.
|
||||||
* @param {string} sku - The article SKU.
|
* @param {string} sku - The article SKU.
|
||||||
* @param {object} [opts] - Optional options.
|
* @param {object} [opts] - Optional pagination and filter options.
|
||||||
* @param {number} [opts.limit] - Maximum number of entries to return (newest first).
|
* @param {number} [opts.offset=0] - Number of entries to skip.
|
||||||
|
* @param {number} [opts.limit=50] - Number of entries to return.
|
||||||
|
* @param {string} [opts.search] - Optional search filter for history text.
|
||||||
|
* @param {number} [opts.seekMonths] - Negative integer cutoff months ago.
|
||||||
|
* @param {boolean} [opts.paged] - Explicitly return paged result object.
|
||||||
* @param {object} [tx] - Optional transaction.
|
* @param {object} [tx] - Optional transaction.
|
||||||
* @returns {Promise<Array<{id: number, companyuserId: number|null, date: string, text: string, meta: string|null}>>} The article history entries.
|
* @returns {Promise<{history: Array<{id: number, companyuserId: number|null, date: string, text: string, meta: string|null}>, total: number, unfilteredTotal: number, offset: number, limit: number}|Array<{id: number, companyuserId: number|null, date: string, text: string, meta: string|null}>>} The article history entries.
|
||||||
*
|
*
|
||||||
* @example
|
* @example
|
||||||
|
* const result = await store.article.getHistoryBySku(42, 'SKU-1', { offset: 0, limit: 50, search: 'Tee' });
|
||||||
|
* // => { history: [...], total, unfilteredTotal, offset, limit }
|
||||||
|
*
|
||||||
* const history = await store.article.getHistoryBySku(42, 'SKU-1');
|
* const history = await store.article.getHistoryBySku(42, 'SKU-1');
|
||||||
* // => [{ id, companyuserId, date, text, meta }]
|
* // => [{ id, companyuserId, date, text, meta }]
|
||||||
*
|
|
||||||
* const recent = await store.article.getHistoryBySku(42, 'SKU-1', { limit: 5 });
|
|
||||||
* // => up to 5 most recent entries
|
|
||||||
*/
|
*/
|
||||||
return async (googleAuthId, sku, opts, tx) => {
|
return async (googleAuthId, sku, opts, tx) => {
|
||||||
// Support legacy call signature: getHistoryBySku(googleAuthId, sku, tx)
|
let offset = 0;
|
||||||
let limit = null;
|
let limit = 50;
|
||||||
|
let isPaged = false;
|
||||||
let resolvedTx = tx;
|
let resolvedTx = tx;
|
||||||
|
|
||||||
|
const hasFilter = opts != null && typeof opts === 'object' && !opts._isTx && (
|
||||||
|
opts.offset !== undefined ||
|
||||||
|
opts.paged === true ||
|
||||||
|
(typeof opts.search === 'string' && opts.search.trim() !== '') ||
|
||||||
|
opts.seekMonths !== undefined
|
||||||
|
);
|
||||||
|
|
||||||
if (opts != null && typeof opts === 'object' && !opts._isTx) {
|
if (opts != null && typeof opts === 'object' && !opts._isTx) {
|
||||||
limit = opts.limit != null ? Number(opts.limit) : null;
|
if (hasFilter || opts.paged === true) {
|
||||||
|
isPaged = true;
|
||||||
|
if (opts.offset !== undefined) {
|
||||||
|
const parsedOffset = Number(opts.offset);
|
||||||
|
if (!Number.isInteger(parsedOffset) || parsedOffset < 0) {
|
||||||
|
throw new Error('Invalid offset');
|
||||||
|
}
|
||||||
|
offset = parsedOffset;
|
||||||
|
}
|
||||||
|
if (opts.limit !== undefined) {
|
||||||
|
const parsedLimit = Number(opts.limit);
|
||||||
|
if (!Number.isInteger(parsedLimit) || parsedLimit < 1) {
|
||||||
|
throw new Error('Invalid limit');
|
||||||
|
}
|
||||||
|
limit = parsedLimit;
|
||||||
|
}
|
||||||
|
} else if (opts.limit != null) {
|
||||||
|
limit = Number(opts.limit);
|
||||||
|
}
|
||||||
} else if (opts != null) {
|
} else if (opts != null) {
|
||||||
resolvedTx = opts;
|
resolvedTx = opts;
|
||||||
}
|
}
|
||||||
@@ -39,17 +66,124 @@ export default function getHistoryBySku(provider) {
|
|||||||
const runner = makeRunner(provider, resolvedTx);
|
const runner = makeRunner(provider, resolvedTx);
|
||||||
const { articleId } = await resolve(googleAuthId, sku, runner);
|
const { articleId } = await resolve(googleAuthId, sku, runner);
|
||||||
|
|
||||||
let result;
|
const conditions = ['ah.article_id = @articleId'];
|
||||||
if (limit != null && Number.isInteger(limit) && limit > 0) {
|
const params = {
|
||||||
result = await runner.query(sqlLimited, { articleId, limit });
|
articleId,
|
||||||
} else {
|
};
|
||||||
result = await runner.query(sql, { articleId });
|
|
||||||
|
if (opts?.seekMonths !== undefined) {
|
||||||
|
if (typeof opts.seekMonths !== 'number' || !Number.isInteger(opts.seekMonths)) {
|
||||||
|
throw new Error('Invalid seekMonths');
|
||||||
|
}
|
||||||
|
const d = new Date();
|
||||||
|
d.setMonth(d.getMonth() - Math.abs(opts.seekMonths));
|
||||||
|
params.dateTo = d.toISOString();
|
||||||
|
conditions.push(`ah.${isSqlite ? '"date"' : '[date]'} <= @dateTo`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (typeof opts?.search === 'string' && opts.search.trim() !== '') {
|
||||||
|
params.searchPattern = `%${opts.search.trim()}%`;
|
||||||
|
conditions.push(`ah.${isSqlite ? '"text"' : '[text]'} LIKE @searchPattern`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const whereClause = conditions.join('\n AND ');
|
||||||
|
|
||||||
|
const sqlCount = `
|
||||||
|
SELECT COUNT(*) AS total
|
||||||
|
FROM articlehistory ah
|
||||||
|
WHERE ${whereClause}
|
||||||
|
`;
|
||||||
|
|
||||||
|
const sqlCountBase = `
|
||||||
|
SELECT COUNT(*) AS total
|
||||||
|
FROM articlehistory ah
|
||||||
|
WHERE ah.article_id = @articleId
|
||||||
|
`;
|
||||||
|
|
||||||
|
let sqlList;
|
||||||
|
if (isSqlite) {
|
||||||
|
sqlList = `
|
||||||
|
SELECT
|
||||||
|
ah.id,
|
||||||
|
ah.companyuser_id AS companyuserId,
|
||||||
|
ah."date",
|
||||||
|
ah."text",
|
||||||
|
ah.meta
|
||||||
|
FROM articlehistory ah
|
||||||
|
WHERE ${whereClause}
|
||||||
|
ORDER BY ah."date" DESC, ah.id DESC
|
||||||
|
${isPaged ? 'LIMIT @limit OFFSET @offset' : (limit != null && limit > 0 ? 'LIMIT @limit' : '')}
|
||||||
|
`;
|
||||||
|
} else {
|
||||||
|
sqlList = `
|
||||||
|
SELECT
|
||||||
|
${!isPaged && limit != null && limit > 0 ? 'TOP (@limit)' : ''}
|
||||||
|
ah.id,
|
||||||
|
ah.companyuser_id AS companyuserId,
|
||||||
|
ah.[date],
|
||||||
|
ah.[text],
|
||||||
|
ah.meta
|
||||||
|
FROM articlehistory ah
|
||||||
|
WHERE ${whereClause}
|
||||||
|
ORDER BY ah.[date] DESC, ah.id DESC
|
||||||
|
${isPaged ? 'OFFSET @offset ROWS FETCH NEXT @limit ROWS ONLY' : ''}
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isPaged) {
|
||||||
|
params.offset = offset;
|
||||||
|
params.limit = limit;
|
||||||
|
|
||||||
|
const hasUserFilters = (
|
||||||
|
opts?.seekMonths !== undefined ||
|
||||||
|
(typeof opts?.search === 'string' && opts.search.trim() !== '')
|
||||||
|
);
|
||||||
|
|
||||||
|
const [countResult, listResult, unfilteredCountResult] = await Promise.all([
|
||||||
|
runner.query(sqlCount, params),
|
||||||
|
runner.query(sqlList, params),
|
||||||
|
hasUserFilters ? runner.query(sqlCountBase, { articleId }) : null,
|
||||||
|
]);
|
||||||
|
|
||||||
|
const total = Number(countResult.rows[0]?.total ?? 0);
|
||||||
|
const unfilteredTotal = hasUserFilters
|
||||||
|
? Number(unfilteredCountResult?.rows[0]?.total ?? 0)
|
||||||
|
: total;
|
||||||
|
|
||||||
|
return {
|
||||||
|
history: listResult.rows.map((row) => ({
|
||||||
|
id: row.id,
|
||||||
|
companyuserId: row.companyuserId ?? null,
|
||||||
|
date:
|
||||||
|
row.date instanceof Date
|
||||||
|
? row.date.toISOString()
|
||||||
|
: row.date
|
||||||
|
? new Date(row.date).toISOString()
|
||||||
|
: null,
|
||||||
|
text: row.text,
|
||||||
|
meta: row.meta ?? null,
|
||||||
|
})),
|
||||||
|
total,
|
||||||
|
unfilteredTotal,
|
||||||
|
offset,
|
||||||
|
limit,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (limit != null && limit > 0) {
|
||||||
|
params.limit = limit;
|
||||||
|
}
|
||||||
|
|
||||||
|
const result = await runner.query(sqlList, params);
|
||||||
return result.rows.map((row) => ({
|
return result.rows.map((row) => ({
|
||||||
id: row.id,
|
id: row.id,
|
||||||
companyuserId: row.companyuserId ?? null,
|
companyuserId: row.companyuserId ?? null,
|
||||||
date: row.date,
|
date:
|
||||||
|
row.date instanceof Date
|
||||||
|
? row.date.toISOString()
|
||||||
|
: row.date
|
||||||
|
? new Date(row.date).toISOString()
|
||||||
|
: null,
|
||||||
text: row.text,
|
text: row.text,
|
||||||
meta: row.meta ?? null,
|
meta: row.meta ?? null,
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -307,6 +307,26 @@ describe('store.article', () => {
|
|||||||
const limited = await store.article.getHistoryBySku(gid, art.sku, { limit: 1 });
|
const limited = await store.article.getHistoryBySku(gid, art.sku, { limit: 1 });
|
||||||
assert.equal(limited.length, 1);
|
assert.equal(limited.length, 1);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('supports pagination with total and unfilteredTotal', async () => {
|
||||||
|
const art = await createArticle(store, tenant, { name: 'PagedH0' });
|
||||||
|
await store.article.updateBySku(gid, art.sku, { name: 'PagedH1' });
|
||||||
|
await store.article.updateBySku(gid, art.sku, { name: 'PagedH2' });
|
||||||
|
|
||||||
|
const paged = await store.article.getHistoryBySku(gid, art.sku, { offset: 0, limit: 2 });
|
||||||
|
assert.equal(typeof paged, 'object');
|
||||||
|
assert.ok(Array.isArray(paged.history));
|
||||||
|
assert.equal(paged.history.length, 2);
|
||||||
|
assert.equal(paged.offset, 0);
|
||||||
|
assert.equal(paged.limit, 2);
|
||||||
|
assert.equal(paged.total, 3);
|
||||||
|
assert.equal(paged.unfilteredTotal, 3);
|
||||||
|
|
||||||
|
const filtered = await store.article.getHistoryBySku(gid, art.sku, { offset: 0, limit: 50, search: 'PagedH2' });
|
||||||
|
assert.equal(filtered.total, 1);
|
||||||
|
assert.equal(filtered.unfilteredTotal, 3);
|
||||||
|
assert.equal(filtered.history.length, 1);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('listSearchIndex / listExport', () => {
|
describe('listSearchIndex / listExport', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user