@propeller-commerce/propeller-sdk-v2 0.14.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -4,6 +4,53 @@ All notable changes to `@propeller-commerce/propeller-sdk-v2` are documented her
4
4
 
5
5
  ---
6
6
 
7
+ ## [0.15.0] - 2026-08-04
8
+
9
+ Exposes the backend inventory/stock filter so storefronts can filter catalogue
10
+ and category listings by stock. Additive and backward-compatible — the filter
11
+ is optional everywhere it appears.
12
+
13
+ Filtering is applied server-side, so the pagination fields on the response
14
+ (`itemsFound`, `pages`) describe the filtered set and can be used directly for
15
+ paging.
16
+
17
+ ### Added
18
+
19
+ - **`ProductSearchInventoryFilterInput`** — new exported type with
20
+ `totalQuantity`, `localQuantity` and `supplierQuantity`, each a
21
+ `NumberSearchInput`.
22
+ - Optional `inventory` field on all five product-search inputs that accept it
23
+ upstream: `ProductSearchInput`, `CategoryProductSearchInput`,
24
+ `ProductSearchByCategoryInput`, `ProductSearchSearchInput` and
25
+ `SparePartsMachineProductSearchInput`. No service or operation changes were
26
+ needed — these inputs are already passed through as variables, so the filter
27
+ is reachable from `productService.getProducts({ input })`,
28
+ `productSearchByCategory({ input })` and the `categoryProductSearchInput`
29
+ variable on the category queries.
30
+ - `docs/content/guides/stock-filtering.md` and a README section covering the
31
+ operator semantics.
32
+ - `tests/service/ProductInventoryFilter.integration.test.ts` — guards that the
33
+ filter is applied server-side and that `lessThan` really is inclusive.
34
+
35
+ ### Notes
36
+
37
+ `NumberSearchInput`'s range operators are **inclusive** despite their names:
38
+ `greaterThan: N` is stock **>= N** and `lessThan: N` is stock **<= N**.
39
+ Never-stocked products have no inventory record and count as **0**. So:
40
+
41
+ - in stock — `{ totalQuantity: { greaterThan: 1 } }` (>= 1; correctly includes
42
+ products with exactly 1 left)
43
+ - out of stock — `{ totalQuantity: { equal: 0 } }`, or
44
+ `{ totalQuantity: { lessThan: 0 } }` (<= 0) to also catch negative balances
45
+
46
+ Do **not** use `lessThan: 1` for out-of-stock — it means <= 1 and includes
47
+ in-stock products with one item remaining.
48
+
49
+ The committed schema snapshot is refreshed to the production introspection that
50
+ carries this filter.
51
+
52
+ ---
53
+
7
54
  ## [0.14.0] - 2026-07-28
8
55
 
9
56
  **Breaking.** Removes the entire deprecated surface — every operation, field
package/README.md CHANGED
@@ -238,6 +238,25 @@ that the whole entity was fetched.
238
238
  > [`src/generated/operations/`](./src/generated/operations/) (or the
239
239
  > [API docs](https://propeller-commerce.github.io/propeller-sdk-v2/)).
240
240
 
241
+ ### Stock filtering
242
+
243
+ Product searches take an `inventory` filter, applied server-side — so
244
+ `itemsFound` and `pages` describe the filtered set and can be used directly for
245
+ paging:
246
+
247
+ ```typescript
248
+ const inStock = await products.getProducts({
249
+ input: { page: 1, offset: 24, inventory: { totalQuantity: { greaterThan: 1 } } },
250
+ });
251
+ ```
252
+
253
+ `greaterThan` and `lessThan` are **inclusive** (`greaterThan: N` is stock >= N,
254
+ `lessThan: N` is stock <= N), and never-stocked products count as 0. So in stock
255
+ is `greaterThan: 1` and out of stock is `equal: 0` (or `lessThan: 0` to include
256
+ negative balances) — **not** `lessThan: 1`, which means <= 1 and would include
257
+ products with one item left. Full detail in the
258
+ [stock filtering guide](https://propeller-commerce.github.io/propeller-sdk-v2/guides/stock-filtering).
259
+
241
260
  ## Direct GraphQL access
242
261
 
243
262
  For ad-hoc queries that aren't covered by a service:
@@ -7,6 +7,7 @@ import { ProductPriceFilterInput } from './ProductPriceFilterInput';
7
7
  import { ProductSortInput } from './ProductSortInput';
8
8
  import { SearchFieldsInput } from './SearchFieldsInput';
9
9
  import { DateSearchInput } from './DateSearchInput';
10
+ import { ProductSearchInventoryFilterInput } from './ProductSearchInventoryFilterInput';
10
11
  /**
11
12
  Input object for CategoryProductSearchInput
12
13
  */
@@ -76,4 +77,9 @@ export interface CategoryProductSearchInput {
76
77
  skus?: string[];
77
78
  /** [Deprecated] Category path for hierarchical navigation. */
78
79
  path?: string;
80
+ /** Server-side stock filter. Operators are inclusive: `greaterThan: N` is
81
+ stock >= N and `lessThan: N` is stock <= N. Never-stocked products count
82
+ as 0. Filtering is applied upstream, so `itemsFound` / `pages` reflect
83
+ the filtered set. */
84
+ inventory?: ProductSearchInventoryFilterInput;
79
85
  }
@@ -8,6 +8,7 @@ import { ProductSearchSortInput } from './ProductSearchSortInput';
8
8
  import { ProductSearchTextFilterInput } from './ProductSearchTextFilterInput';
9
9
  import { ProductStatus } from '../enum/ProductStatus';
10
10
  import { YesNo } from '../enum/YesNo';
11
+ import { ProductSearchInventoryFilterInput } from './ProductSearchInventoryFilterInput';
11
12
  /**
12
13
  Input object for ProductSearchByCategoryInput
13
14
  */
@@ -82,4 +83,9 @@ export interface ProductSearchByCategoryInput {
82
83
  applyOrderlists?: boolean;
83
84
  /** Order list IDs to apply for filtering */
84
85
  orderlistIds?: number[];
86
+ /** Server-side stock filter. Operators are inclusive: `greaterThan: N` is
87
+ stock >= N and `lessThan: N` is stock <= N. Never-stocked products count
88
+ as 0. Filtering is applied upstream, so `itemsFound` / `pages` reflect
89
+ the filtered set. */
90
+ inventory?: ProductSearchInventoryFilterInput;
85
91
  }
@@ -7,6 +7,7 @@ import { ProductPriceFilterInput } from './ProductPriceFilterInput';
7
7
  import { ProductSortInput } from './ProductSortInput';
8
8
  import { SearchFieldsInput } from './SearchFieldsInput';
9
9
  import { DateSearchInput } from './DateSearchInput';
10
+ import { ProductSearchInventoryFilterInput } from './ProductSearchInventoryFilterInput';
10
11
  /**
11
12
  Input object for ProductSearchInput
12
13
  */
@@ -78,4 +79,9 @@ export interface ProductSearchInput {
78
79
  applyOrderlists?: boolean;
79
80
  /** List orderlists to apply */
80
81
  orderlistIds?: number[];
82
+ /** Server-side stock filter. Operators are inclusive: `greaterThan: N` is
83
+ stock >= N and `lessThan: N` is stock <= N. Never-stocked products count
84
+ as 0. Filtering is applied upstream, so `itemsFound` / `pages` reflect
85
+ the filtered set. */
86
+ inventory?: ProductSearchInventoryFilterInput;
81
87
  }
@@ -0,0 +1,30 @@
1
+ import { NumberSearchInput } from './NumberSearchInput';
2
+ /**
3
+ Input object for ProductSearchInventoryFilterInput
4
+
5
+ Server-side stock filter for product search. Because the filtering happens
6
+ upstream, the pagination counts on the response (`itemsFound`, `pages`)
7
+ describe the *filtered* set, so they can be used directly for paging.
8
+
9
+ Products that were never stocked have no inventory record and count as **0**.
10
+
11
+ `NumberSearchInput` operators are inclusive despite their names —
12
+ `greaterThan: N` means stock **>= N** and `lessThan: N` means stock **<= N**:
13
+
14
+ - In stock — `{ totalQuantity: { greaterThan: 1 } }` (>= 1). This includes
15
+ products with exactly 1 in stock, which is correct.
16
+ - Out of stock — `{ totalQuantity: { equal: 0 } }` (exactly 0, including
17
+ never-stocked products), or `{ totalQuantity: { lessThan: 0 } }` (<= 0) to
18
+ also catch negative balances.
19
+
20
+ Do **not** use `lessThan: 1` for out-of-stock: it means <= 1 and therefore
21
+ includes in-stock products that have exactly 1 remaining.
22
+ */
23
+ export interface ProductSearchInventoryFilterInput {
24
+ /** Filter on the total available quantity across all warehouses */
25
+ totalQuantity?: NumberSearchInput;
26
+ /** Filter on the local warehouse quantity */
27
+ localQuantity?: NumberSearchInput;
28
+ /** Filter on the supplier warehouse quantity */
29
+ supplierQuantity?: NumberSearchInput;
30
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -8,6 +8,7 @@ import { ProductSearchSortInput } from './ProductSearchSortInput';
8
8
  import { ProductSearchTextFilterInput } from './ProductSearchTextFilterInput';
9
9
  import { ProductStatus } from '../enum/ProductStatus';
10
10
  import { YesNo } from '../enum/YesNo';
11
+ import { ProductSearchInventoryFilterInput } from './ProductSearchInventoryFilterInput';
11
12
  /**
12
13
  Input object for ProductSearchSearchInput
13
14
  */
@@ -84,4 +85,9 @@ export interface ProductSearchSearchInput {
84
85
  applyOrderlists?: boolean;
85
86
  /** Order list IDs to apply for filtering */
86
87
  orderlistIds?: number[];
88
+ /** Server-side stock filter. Operators are inclusive: `greaterThan: N` is
89
+ stock >= N and `lessThan: N` is stock <= N. Never-stocked products count
90
+ as 0. Filtering is applied upstream, so `itemsFound` / `pages` reflect
91
+ the filtered set. */
92
+ inventory?: ProductSearchInventoryFilterInput;
87
93
  }
@@ -7,6 +7,7 @@ import { ProductPriceFilterInput } from './ProductPriceFilterInput';
7
7
  import { ProductSortInput } from './ProductSortInput';
8
8
  import { SearchFieldsInput } from './SearchFieldsInput';
9
9
  import { DateSearchInput } from './DateSearchInput';
10
+ import { ProductSearchInventoryFilterInput } from './ProductSearchInventoryFilterInput';
10
11
  /**
11
12
  Input object for SparePartsMachineProductSearchInput
12
13
  */
@@ -74,4 +75,9 @@ export interface SparePartsMachineProductSearchInput {
74
75
  skus?: string[];
75
76
  /** [Deprecated] Category path for hierarchical navigation. */
76
77
  path?: string;
78
+ /** Server-side stock filter. Operators are inclusive: `greaterThan: N` is
79
+ stock >= N and `lessThan: N` is stock <= N. Never-stocked products count
80
+ as 0. Filtering is applied upstream, so `itemsFound` / `pages` reflect
81
+ the filtered set. */
82
+ inventory?: ProductSearchInventoryFilterInput;
77
83
  }
@@ -531,6 +531,7 @@ export * from './ProductPrice';
531
531
  export * from './ProductPriceFilterInput';
532
532
  export * from './ProductRangeFilterInput';
533
533
  export * from './ProductSearchInput';
534
+ export * from './ProductSearchInventoryFilterInput';
534
535
  export * from './ProductSortInput';
535
536
  export * from './ProductTextFilterInput';
536
537
  export * from './ProductsResponse';
@@ -547,6 +547,7 @@ __exportStar(require("./ProductPrice"), exports);
547
547
  __exportStar(require("./ProductPriceFilterInput"), exports);
548
548
  __exportStar(require("./ProductRangeFilterInput"), exports);
549
549
  __exportStar(require("./ProductSearchInput"), exports);
550
+ __exportStar(require("./ProductSearchInventoryFilterInput"), exports);
550
551
  __exportStar(require("./ProductSortInput"), exports);
551
552
  __exportStar(require("./ProductTextFilterInput"), exports);
552
553
  __exportStar(require("./ProductsResponse"), exports);
@@ -0,0 +1 @@
1
+ export {};
@@ -531,6 +531,7 @@ export * from './ProductPrice.js';
531
531
  export * from './ProductPriceFilterInput.js';
532
532
  export * from './ProductRangeFilterInput.js';
533
533
  export * from './ProductSearchInput.js';
534
+ export * from './ProductSearchInventoryFilterInput.js';
534
535
  export * from './ProductSortInput.js';
535
536
  export * from './ProductTextFilterInput.js';
536
537
  export * from './ProductsResponse.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@propeller-commerce/propeller-sdk-v2",
3
- "version": "0.14.0",
3
+ "version": "0.15.0",
4
4
  "description": "TypeScript GraphQL client for Propeller eCommerce V2 Platform - works with React, Vue, Angular and all JavaScript frameworks",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",