lua-cli 2.5.0 → 2.5.2
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 +36 -0
- package/dist/api/products.api.service.js +2 -0
- package/dist/common/basket.instance.d.ts +4 -1
- package/dist/common/basket.instance.js +76 -1
- package/dist/common/data.entry.instance.d.ts +4 -1
- package/dist/common/data.entry.instance.js +57 -1
- package/dist/common/order.instance.d.ts +4 -1
- package/dist/common/order.instance.js +76 -1
- package/dist/common/product.instance.d.ts +4 -1
- package/dist/common/product.instance.js +57 -1
- package/dist/common/product.pagination.instance.d.ts +58 -0
- package/dist/common/product.pagination.instance.js +78 -0
- package/dist/common/product.search.instance.d.ts +58 -0
- package/dist/common/product.search.instance.js +78 -0
- package/dist/common/user.instance.d.ts +1 -0
- package/dist/web/app.css +85 -2
- package/dist/web/app.js +43 -43
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,42 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
6
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [2.5.2] - 2025-10-07
|
|
9
|
+
|
|
10
|
+
### ✨ New Features
|
|
11
|
+
- **Direct Property Access for All Instance Classes**: Extended Proxy pattern to all instance types
|
|
12
|
+
- `ProductInstance` now supports `product.name` instead of `product.data.name`
|
|
13
|
+
- `DataEntryInstance` now supports `entry.fieldName` instead of `entry.data.fieldName`
|
|
14
|
+
- `BasketInstance` now supports `basket.items` (checks instance → data → common)
|
|
15
|
+
- `OrderInstance` now supports `order.shippingAddress` (checks instance → data → common)
|
|
16
|
+
|
|
17
|
+
- **Array-Like Methods for Product Collections**: Direct iteration support
|
|
18
|
+
- `ProductSearchInstance` now supports `.map()`, `.filter()`, `.forEach()`, etc.
|
|
19
|
+
- `ProductPaginationInstance` now supports all array methods
|
|
20
|
+
- Both support `for...of` loops and spread operators
|
|
21
|
+
- Direct `.length` property access
|
|
22
|
+
|
|
23
|
+
### 🔧 Improvements
|
|
24
|
+
- **Consistent API**: All instance classes now follow the same intuitive access patterns
|
|
25
|
+
- **Enhanced Iteration**: Product collections can be treated as arrays
|
|
26
|
+
- **Better TypeScript Support**: Index signatures on all instance classes
|
|
27
|
+
|
|
28
|
+
### 📖 Documentation
|
|
29
|
+
- **Comprehensive Instance Types Documentation**: Added complete guide for all instance types
|
|
30
|
+
|
|
31
|
+
### Technical Details
|
|
32
|
+
- Added Proxy implementations to ProductInstance, DataEntryInstance, BasketInstance, OrderInstance
|
|
33
|
+
- Added array method delegation to ProductSearchInstance and ProductPaginationInstance
|
|
34
|
+
- Added Symbol.iterator support for proper iteration
|
|
35
|
+
- Type-safe implementations with proper generics
|
|
36
|
+
|
|
37
|
+
## [2.5.1] - 2025-10-07
|
|
38
|
+
|
|
39
|
+
### 🐛 Bug Fixes
|
|
40
|
+
- **TypeScript Index Signature**: Added index signature to `UserDataInstance` class to fix TypeScript linting errors
|
|
41
|
+
- Resolves "Property does not exist on type" errors when accessing dynamic properties like `user.name`
|
|
42
|
+
- Now properly typed for dynamic property access via Proxy
|
|
43
|
+
|
|
8
44
|
## [2.5.0] - 2025-10-07
|
|
9
45
|
|
|
10
46
|
### ✨ New Features
|
|
@@ -25,9 +25,11 @@ export default class ProductApi extends HttpClient {
|
|
|
25
25
|
* @throws Error if the request fails or products cannot be retrieved
|
|
26
26
|
*/
|
|
27
27
|
async get(page = 1, limit = 10) {
|
|
28
|
+
console.log('get products', page, limit, this.agentId, this.apiKey);
|
|
28
29
|
const response = await this.httpGet(`/developer/agents/${this.agentId}/products?page=${page}&limit=${limit}`, {
|
|
29
30
|
Authorization: `Bearer ${this.apiKey}`,
|
|
30
31
|
});
|
|
32
|
+
console.log('get products response', response);
|
|
31
33
|
if (response.success) {
|
|
32
34
|
return new ProductPaginationInstance(this, response);
|
|
33
35
|
}
|
|
@@ -4,6 +4,7 @@ import OrderInstance from "./order.instance.js";
|
|
|
4
4
|
/**
|
|
5
5
|
* Basket instance class providing a fluent API for managing user baskets
|
|
6
6
|
* Provides methods for adding/removing items, updating metadata, and placing orders
|
|
7
|
+
* Supports direct property access (e.g., basket.items) for accessing data and common properties
|
|
7
8
|
*/
|
|
8
9
|
export default class BasketInstance {
|
|
9
10
|
private id;
|
|
@@ -16,10 +17,12 @@ export default class BasketInstance {
|
|
|
16
17
|
itemCount: number;
|
|
17
18
|
status: BasketStatus;
|
|
18
19
|
private basketAPI;
|
|
20
|
+
[key: string]: any;
|
|
19
21
|
/**
|
|
20
|
-
* Creates a new BasketInstance
|
|
22
|
+
* Creates a new BasketInstance with proxy support for direct property access
|
|
21
23
|
* @param api - The BasketAPI instance for making API calls
|
|
22
24
|
* @param basket - The basket data from the API
|
|
25
|
+
* @returns Proxied instance that allows direct access to data and common properties
|
|
23
26
|
*/
|
|
24
27
|
constructor(api: BasketAPI, basket: Basket);
|
|
25
28
|
/**
|
|
@@ -2,12 +2,14 @@ import { BasketStatus } from "../interfaces/baskets.js";
|
|
|
2
2
|
/**
|
|
3
3
|
* Basket instance class providing a fluent API for managing user baskets
|
|
4
4
|
* Provides methods for adding/removing items, updating metadata, and placing orders
|
|
5
|
+
* Supports direct property access (e.g., basket.items) for accessing data and common properties
|
|
5
6
|
*/
|
|
6
7
|
export default class BasketInstance {
|
|
7
8
|
/**
|
|
8
|
-
* Creates a new BasketInstance
|
|
9
|
+
* Creates a new BasketInstance with proxy support for direct property access
|
|
9
10
|
* @param api - The BasketAPI instance for making API calls
|
|
10
11
|
* @param basket - The basket data from the API
|
|
12
|
+
* @returns Proxied instance that allows direct access to data and common properties
|
|
11
13
|
*/
|
|
12
14
|
constructor(api, basket) {
|
|
13
15
|
this.data = basket.data;
|
|
@@ -26,6 +28,79 @@ export default class BasketInstance {
|
|
|
26
28
|
enumerable: false,
|
|
27
29
|
configurable: true
|
|
28
30
|
});
|
|
31
|
+
// Return a proxy that allows direct property access
|
|
32
|
+
return new Proxy(this, {
|
|
33
|
+
get(target, prop, receiver) {
|
|
34
|
+
// If the property exists on the instance itself, return it
|
|
35
|
+
if (prop in target) {
|
|
36
|
+
return Reflect.get(target, prop, receiver);
|
|
37
|
+
}
|
|
38
|
+
// Check data object
|
|
39
|
+
if (typeof prop === 'string' && prop in target.data) {
|
|
40
|
+
return target.data[prop];
|
|
41
|
+
}
|
|
42
|
+
// Check common object
|
|
43
|
+
if (typeof prop === 'string' && prop in target.common) {
|
|
44
|
+
return target.common[prop];
|
|
45
|
+
}
|
|
46
|
+
return undefined;
|
|
47
|
+
},
|
|
48
|
+
set(target, prop, value, receiver) {
|
|
49
|
+
// Reserved properties that should be set on the instance itself
|
|
50
|
+
const reservedProps = ['id', 'userId', 'agentId', 'data', 'common', 'metadata', 'totalAmount', 'itemCount', 'status', 'basketAPI', 'updateMetadata', 'updateStatus', 'addItem', 'removeItem', 'clear', 'placeOrder', 'toJSON'];
|
|
51
|
+
if (typeof prop === 'string' && reservedProps.includes(prop)) {
|
|
52
|
+
return Reflect.set(target, prop, value, receiver);
|
|
53
|
+
}
|
|
54
|
+
// Check if property exists in data or common, otherwise default to data
|
|
55
|
+
if (typeof prop === 'string') {
|
|
56
|
+
if (prop in target.common) {
|
|
57
|
+
target.common[prop] = value;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
target.data[prop] = value;
|
|
61
|
+
}
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
return false;
|
|
65
|
+
},
|
|
66
|
+
has(target, prop) {
|
|
67
|
+
// Check if property exists on instance, in data, or in common
|
|
68
|
+
return prop in target || (typeof prop === 'string' && (prop in target.data || prop in target.common));
|
|
69
|
+
},
|
|
70
|
+
ownKeys(target) {
|
|
71
|
+
// Return instance keys, data keys, and common keys
|
|
72
|
+
const instanceKeys = Reflect.ownKeys(target);
|
|
73
|
+
const dataKeys = Object.keys(target.data);
|
|
74
|
+
const commonKeys = Object.keys(target.common);
|
|
75
|
+
return [...new Set([...instanceKeys, ...dataKeys, ...commonKeys])];
|
|
76
|
+
},
|
|
77
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
78
|
+
// First check if it's an instance property
|
|
79
|
+
const instanceDesc = Reflect.getOwnPropertyDescriptor(target, prop);
|
|
80
|
+
if (instanceDesc) {
|
|
81
|
+
return instanceDesc;
|
|
82
|
+
}
|
|
83
|
+
// Then check data properties
|
|
84
|
+
if (typeof prop === 'string' && prop in target.data) {
|
|
85
|
+
return {
|
|
86
|
+
configurable: true,
|
|
87
|
+
enumerable: true,
|
|
88
|
+
writable: true,
|
|
89
|
+
value: target.data[prop]
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// Then check common properties
|
|
93
|
+
if (typeof prop === 'string' && prop in target.common) {
|
|
94
|
+
return {
|
|
95
|
+
configurable: true,
|
|
96
|
+
enumerable: true,
|
|
97
|
+
writable: true,
|
|
98
|
+
value: target.common[prop]
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return undefined;
|
|
102
|
+
}
|
|
103
|
+
});
|
|
29
104
|
}
|
|
30
105
|
/**
|
|
31
106
|
* Custom toJSON method to control what gets serialized when logging
|
|
@@ -3,6 +3,7 @@ import { CreateCustomDataResponse } from "../interfaces/custom.data.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Data entry instance class providing a fluent API for managing custom data entries
|
|
5
5
|
* Provides methods for updating and deleting individual data entries
|
|
6
|
+
* Supports direct property access (e.g., entry.fieldName) for accessing data properties
|
|
6
7
|
*/
|
|
7
8
|
export default class DataEntryInstance {
|
|
8
9
|
data: Record<string, any>;
|
|
@@ -10,11 +11,13 @@ export default class DataEntryInstance {
|
|
|
10
11
|
collectionName: string;
|
|
11
12
|
score?: number;
|
|
12
13
|
private customDataAPI;
|
|
14
|
+
[key: string]: any;
|
|
13
15
|
/**
|
|
14
|
-
* Creates a new DataEntryInstance
|
|
16
|
+
* Creates a new DataEntryInstance with proxy support for direct property access
|
|
15
17
|
* @param api - The CustomDataAPI instance for making API calls
|
|
16
18
|
* @param entry - The custom data entry response from the API
|
|
17
19
|
* @param collectionName - The name of the collection this entry belongs to
|
|
20
|
+
* @returns Proxied instance that allows direct access to data properties
|
|
18
21
|
*/
|
|
19
22
|
constructor(api: CustomDataAPI, entry: CreateCustomDataResponse, collectionName: string);
|
|
20
23
|
/**
|
|
@@ -1,13 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Data entry instance class providing a fluent API for managing custom data entries
|
|
3
3
|
* Provides methods for updating and deleting individual data entries
|
|
4
|
+
* Supports direct property access (e.g., entry.fieldName) for accessing data properties
|
|
4
5
|
*/
|
|
5
6
|
export default class DataEntryInstance {
|
|
6
7
|
/**
|
|
7
|
-
* Creates a new DataEntryInstance
|
|
8
|
+
* Creates a new DataEntryInstance with proxy support for direct property access
|
|
8
9
|
* @param api - The CustomDataAPI instance for making API calls
|
|
9
10
|
* @param entry - The custom data entry response from the API
|
|
10
11
|
* @param collectionName - The name of the collection this entry belongs to
|
|
12
|
+
* @returns Proxied instance that allows direct access to data properties
|
|
11
13
|
*/
|
|
12
14
|
constructor(api, entry, collectionName) {
|
|
13
15
|
this.data = entry.data;
|
|
@@ -21,6 +23,60 @@ export default class DataEntryInstance {
|
|
|
21
23
|
enumerable: false,
|
|
22
24
|
configurable: true
|
|
23
25
|
});
|
|
26
|
+
// Return a proxy that allows direct property access
|
|
27
|
+
return new Proxy(this, {
|
|
28
|
+
get(target, prop, receiver) {
|
|
29
|
+
// If the property exists on the instance itself, return it
|
|
30
|
+
if (prop in target) {
|
|
31
|
+
return Reflect.get(target, prop, receiver);
|
|
32
|
+
}
|
|
33
|
+
// Otherwise, try to get it from the data object
|
|
34
|
+
if (typeof prop === 'string' && prop in target.data) {
|
|
35
|
+
return target.data[prop];
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
},
|
|
39
|
+
set(target, prop, value, receiver) {
|
|
40
|
+
// Reserved properties that should be set on the instance itself
|
|
41
|
+
const reservedProps = ['data', 'id', 'collectionName', 'score', 'customDataAPI', 'update', 'delete', 'toJSON'];
|
|
42
|
+
if (typeof prop === 'string' && reservedProps.includes(prop)) {
|
|
43
|
+
return Reflect.set(target, prop, value, receiver);
|
|
44
|
+
}
|
|
45
|
+
// All other properties get set on the data object
|
|
46
|
+
if (typeof prop === 'string') {
|
|
47
|
+
target.data[prop] = value;
|
|
48
|
+
return true;
|
|
49
|
+
}
|
|
50
|
+
return false;
|
|
51
|
+
},
|
|
52
|
+
has(target, prop) {
|
|
53
|
+
// Check if property exists on instance or in data
|
|
54
|
+
return prop in target || (typeof prop === 'string' && prop in target.data);
|
|
55
|
+
},
|
|
56
|
+
ownKeys(target) {
|
|
57
|
+
// Return both instance keys and data keys
|
|
58
|
+
const instanceKeys = Reflect.ownKeys(target);
|
|
59
|
+
const dataKeys = Object.keys(target.data);
|
|
60
|
+
return [...new Set([...instanceKeys, ...dataKeys])];
|
|
61
|
+
},
|
|
62
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
63
|
+
// First check if it's an instance property
|
|
64
|
+
const instanceDesc = Reflect.getOwnPropertyDescriptor(target, prop);
|
|
65
|
+
if (instanceDesc) {
|
|
66
|
+
return instanceDesc;
|
|
67
|
+
}
|
|
68
|
+
// Then check if it's a data property
|
|
69
|
+
if (typeof prop === 'string' && prop in target.data) {
|
|
70
|
+
return {
|
|
71
|
+
configurable: true,
|
|
72
|
+
enumerable: true,
|
|
73
|
+
writable: true,
|
|
74
|
+
value: target.data[prop]
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
return undefined;
|
|
78
|
+
}
|
|
79
|
+
});
|
|
24
80
|
}
|
|
25
81
|
/**
|
|
26
82
|
* Custom toJSON method to control what gets serialized when logging
|
|
@@ -3,6 +3,7 @@ import { OrderResponse, OrderStatus } from "../interfaces/orders.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Order instance class providing a fluent API for managing orders
|
|
5
5
|
* Provides methods for updating order status and order data
|
|
6
|
+
* Supports direct property access (e.g., order.shippingAddress) for accessing data and common properties
|
|
6
7
|
*/
|
|
7
8
|
export default class OrderInstance {
|
|
8
9
|
private data;
|
|
@@ -12,10 +13,12 @@ export default class OrderInstance {
|
|
|
12
13
|
private agentId;
|
|
13
14
|
private orderId;
|
|
14
15
|
private orderAPI;
|
|
16
|
+
[key: string]: any;
|
|
15
17
|
/**
|
|
16
|
-
* Creates a new OrderInstance
|
|
18
|
+
* Creates a new OrderInstance with proxy support for direct property access
|
|
17
19
|
* @param api - The OrderApi instance for making API calls
|
|
18
20
|
* @param order - The order response data from the API
|
|
21
|
+
* @returns Proxied instance that allows direct access to data and common properties
|
|
19
22
|
*/
|
|
20
23
|
constructor(api: OrderApi, order: OrderResponse);
|
|
21
24
|
/**
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Order instance class providing a fluent API for managing orders
|
|
3
3
|
* Provides methods for updating order status and order data
|
|
4
|
+
* Supports direct property access (e.g., order.shippingAddress) for accessing data and common properties
|
|
4
5
|
*/
|
|
5
6
|
export default class OrderInstance {
|
|
6
7
|
/**
|
|
7
|
-
* Creates a new OrderInstance
|
|
8
|
+
* Creates a new OrderInstance with proxy support for direct property access
|
|
8
9
|
* @param api - The OrderApi instance for making API calls
|
|
9
10
|
* @param order - The order response data from the API
|
|
11
|
+
* @returns Proxied instance that allows direct access to data and common properties
|
|
10
12
|
*/
|
|
11
13
|
constructor(api, order) {
|
|
12
14
|
this.data = order.data;
|
|
@@ -22,6 +24,79 @@ export default class OrderInstance {
|
|
|
22
24
|
enumerable: false,
|
|
23
25
|
configurable: true
|
|
24
26
|
});
|
|
27
|
+
// Return a proxy that allows direct property access
|
|
28
|
+
return new Proxy(this, {
|
|
29
|
+
get(target, prop, receiver) {
|
|
30
|
+
// If the property exists on the instance itself, return it
|
|
31
|
+
if (prop in target) {
|
|
32
|
+
return Reflect.get(target, prop, receiver);
|
|
33
|
+
}
|
|
34
|
+
// Check data object
|
|
35
|
+
if (typeof prop === 'string' && prop in target.data) {
|
|
36
|
+
return target.data[prop];
|
|
37
|
+
}
|
|
38
|
+
// Check common object
|
|
39
|
+
if (typeof prop === 'string' && prop in target.common) {
|
|
40
|
+
return target.common[prop];
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
},
|
|
44
|
+
set(target, prop, value, receiver) {
|
|
45
|
+
// Reserved properties that should be set on the instance itself
|
|
46
|
+
const reservedProps = ['data', 'common', 'id', 'userId', 'agentId', 'orderId', 'orderAPI', 'updateStatus', 'update', 'toJSON'];
|
|
47
|
+
if (typeof prop === 'string' && reservedProps.includes(prop)) {
|
|
48
|
+
return Reflect.set(target, prop, value, receiver);
|
|
49
|
+
}
|
|
50
|
+
// Check if property exists in data or common, otherwise default to data
|
|
51
|
+
if (typeof prop === 'string') {
|
|
52
|
+
if (prop in target.common) {
|
|
53
|
+
target.common[prop] = value;
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
target.data[prop] = value;
|
|
57
|
+
}
|
|
58
|
+
return true;
|
|
59
|
+
}
|
|
60
|
+
return false;
|
|
61
|
+
},
|
|
62
|
+
has(target, prop) {
|
|
63
|
+
// Check if property exists on instance, in data, or in common
|
|
64
|
+
return prop in target || (typeof prop === 'string' && (prop in target.data || prop in target.common));
|
|
65
|
+
},
|
|
66
|
+
ownKeys(target) {
|
|
67
|
+
// Return instance keys, data keys, and common keys
|
|
68
|
+
const instanceKeys = Reflect.ownKeys(target);
|
|
69
|
+
const dataKeys = Object.keys(target.data);
|
|
70
|
+
const commonKeys = Object.keys(target.common);
|
|
71
|
+
return [...new Set([...instanceKeys, ...dataKeys, ...commonKeys])];
|
|
72
|
+
},
|
|
73
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
74
|
+
// First check if it's an instance property
|
|
75
|
+
const instanceDesc = Reflect.getOwnPropertyDescriptor(target, prop);
|
|
76
|
+
if (instanceDesc) {
|
|
77
|
+
return instanceDesc;
|
|
78
|
+
}
|
|
79
|
+
// Then check data properties
|
|
80
|
+
if (typeof prop === 'string' && prop in target.data) {
|
|
81
|
+
return {
|
|
82
|
+
configurable: true,
|
|
83
|
+
enumerable: true,
|
|
84
|
+
writable: true,
|
|
85
|
+
value: target.data[prop]
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
// Then check common properties
|
|
89
|
+
if (typeof prop === 'string' && prop in target.common) {
|
|
90
|
+
return {
|
|
91
|
+
configurable: true,
|
|
92
|
+
enumerable: true,
|
|
93
|
+
writable: true,
|
|
94
|
+
value: target.common[prop]
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
25
100
|
}
|
|
26
101
|
/**
|
|
27
102
|
* Custom toJSON method to control what gets serialized when logging
|
|
@@ -2,14 +2,17 @@ import { Product } from "../interfaces/product.js";
|
|
|
2
2
|
/**
|
|
3
3
|
* Product instance class providing a fluent API for managing individual products
|
|
4
4
|
* Provides methods for updating and deleting products
|
|
5
|
+
* Supports direct property access (e.g., product.name) instead of product.data.name
|
|
5
6
|
*/
|
|
6
7
|
export default class ProductInstance {
|
|
7
8
|
data: Product;
|
|
8
9
|
private productAPI;
|
|
10
|
+
[key: string]: any;
|
|
9
11
|
/**
|
|
10
|
-
* Creates a new ProductInstance
|
|
12
|
+
* Creates a new ProductInstance with proxy support for direct property access
|
|
11
13
|
* @param api - The ProductAPI instance for making API calls
|
|
12
14
|
* @param product - The product data from the API
|
|
15
|
+
* @returns Proxied instance that allows direct access to product properties
|
|
13
16
|
*/
|
|
14
17
|
constructor(api: any, product: Product);
|
|
15
18
|
/**
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Product instance class providing a fluent API for managing individual products
|
|
3
3
|
* Provides methods for updating and deleting products
|
|
4
|
+
* Supports direct property access (e.g., product.name) instead of product.data.name
|
|
4
5
|
*/
|
|
5
6
|
export default class ProductInstance {
|
|
6
7
|
/**
|
|
7
|
-
* Creates a new ProductInstance
|
|
8
|
+
* Creates a new ProductInstance with proxy support for direct property access
|
|
8
9
|
* @param api - The ProductAPI instance for making API calls
|
|
9
10
|
* @param product - The product data from the API
|
|
11
|
+
* @returns Proxied instance that allows direct access to product properties
|
|
10
12
|
*/
|
|
11
13
|
constructor(api, product) {
|
|
12
14
|
this.data = product;
|
|
@@ -17,6 +19,60 @@ export default class ProductInstance {
|
|
|
17
19
|
enumerable: false,
|
|
18
20
|
configurable: true
|
|
19
21
|
});
|
|
22
|
+
// Return a proxy that allows direct property access
|
|
23
|
+
return new Proxy(this, {
|
|
24
|
+
get(target, prop, receiver) {
|
|
25
|
+
// If the property exists on the instance itself, return it
|
|
26
|
+
if (prop in target) {
|
|
27
|
+
return Reflect.get(target, prop, receiver);
|
|
28
|
+
}
|
|
29
|
+
// Otherwise, try to get it from the data object
|
|
30
|
+
if (typeof prop === 'string' && prop in target.data) {
|
|
31
|
+
return target.data[prop];
|
|
32
|
+
}
|
|
33
|
+
return undefined;
|
|
34
|
+
},
|
|
35
|
+
set(target, prop, value, receiver) {
|
|
36
|
+
// Reserved properties that should be set on the instance itself
|
|
37
|
+
const reservedProps = ['data', 'productAPI', 'update', 'delete', 'toJSON'];
|
|
38
|
+
if (typeof prop === 'string' && reservedProps.includes(prop)) {
|
|
39
|
+
return Reflect.set(target, prop, value, receiver);
|
|
40
|
+
}
|
|
41
|
+
// All other properties get set on the data object
|
|
42
|
+
if (typeof prop === 'string') {
|
|
43
|
+
target.data[prop] = value;
|
|
44
|
+
return true;
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
},
|
|
48
|
+
has(target, prop) {
|
|
49
|
+
// Check if property exists on instance or in data
|
|
50
|
+
return prop in target || (typeof prop === 'string' && prop in target.data);
|
|
51
|
+
},
|
|
52
|
+
ownKeys(target) {
|
|
53
|
+
// Return both instance keys and data keys
|
|
54
|
+
const instanceKeys = Reflect.ownKeys(target);
|
|
55
|
+
const dataKeys = Object.keys(target.data);
|
|
56
|
+
return [...new Set([...instanceKeys, ...dataKeys])];
|
|
57
|
+
},
|
|
58
|
+
getOwnPropertyDescriptor(target, prop) {
|
|
59
|
+
// First check if it's an instance property
|
|
60
|
+
const instanceDesc = Reflect.getOwnPropertyDescriptor(target, prop);
|
|
61
|
+
if (instanceDesc) {
|
|
62
|
+
return instanceDesc;
|
|
63
|
+
}
|
|
64
|
+
// Then check if it's a data property
|
|
65
|
+
if (typeof prop === 'string' && prop in target.data) {
|
|
66
|
+
return {
|
|
67
|
+
configurable: true,
|
|
68
|
+
enumerable: true,
|
|
69
|
+
writable: true,
|
|
70
|
+
value: target.data[prop]
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
});
|
|
20
76
|
}
|
|
21
77
|
/**
|
|
22
78
|
* Custom toJSON method to control what gets serialized when logging
|
|
@@ -3,6 +3,7 @@ import ProductInstance from "./product.instance.js";
|
|
|
3
3
|
/**
|
|
4
4
|
* Product pagination instance class providing a fluent API for paginated product results
|
|
5
5
|
* Provides methods for navigating through pages of products
|
|
6
|
+
* Supports array methods like map, filter, forEach for direct iteration
|
|
6
7
|
*/
|
|
7
8
|
export default class ProductPaginationInstance {
|
|
8
9
|
products: ProductInstance[];
|
|
@@ -23,6 +24,63 @@ export default class ProductPaginationInstance {
|
|
|
23
24
|
* @param results - The paginated product results from the API
|
|
24
25
|
*/
|
|
25
26
|
constructor(api: any, results: ProductsResponse);
|
|
27
|
+
/**
|
|
28
|
+
* Returns the number of products in the current page
|
|
29
|
+
*/
|
|
30
|
+
get length(): number;
|
|
31
|
+
/**
|
|
32
|
+
* Maps over the products array
|
|
33
|
+
* @param callback - Function to execute for each product
|
|
34
|
+
* @returns Array of mapped results
|
|
35
|
+
*/
|
|
36
|
+
map<T>(callback: (product: ProductInstance, index: number, array: ProductInstance[]) => T): T[];
|
|
37
|
+
/**
|
|
38
|
+
* Filters the products array
|
|
39
|
+
* @param callback - Function to test each product
|
|
40
|
+
* @returns Array of products that pass the test
|
|
41
|
+
*/
|
|
42
|
+
filter(callback: (product: ProductInstance, index: number, array: ProductInstance[]) => boolean): ProductInstance[];
|
|
43
|
+
/**
|
|
44
|
+
* Executes a function for each product
|
|
45
|
+
* @param callback - Function to execute for each product
|
|
46
|
+
*/
|
|
47
|
+
forEach(callback: (product: ProductInstance, index: number, array: ProductInstance[]) => void): void;
|
|
48
|
+
/**
|
|
49
|
+
* Finds the first product that satisfies the test
|
|
50
|
+
* @param callback - Function to test each product
|
|
51
|
+
* @returns The first product that passes the test, or undefined
|
|
52
|
+
*/
|
|
53
|
+
find(callback: (product: ProductInstance, index: number, array: ProductInstance[]) => boolean): ProductInstance | undefined;
|
|
54
|
+
/**
|
|
55
|
+
* Finds the index of the first product that satisfies the test
|
|
56
|
+
* @param callback - Function to test each product
|
|
57
|
+
* @returns The index of the first product that passes the test, or -1
|
|
58
|
+
*/
|
|
59
|
+
findIndex(callback: (product: ProductInstance, index: number, array: ProductInstance[]) => boolean): number;
|
|
60
|
+
/**
|
|
61
|
+
* Checks if some products satisfy the test
|
|
62
|
+
* @param callback - Function to test each product
|
|
63
|
+
* @returns true if at least one product passes the test
|
|
64
|
+
*/
|
|
65
|
+
some(callback: (product: ProductInstance, index: number, array: ProductInstance[]) => boolean): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Checks if all products satisfy the test
|
|
68
|
+
* @param callback - Function to test each product
|
|
69
|
+
* @returns true if all products pass the test
|
|
70
|
+
*/
|
|
71
|
+
every(callback: (product: ProductInstance, index: number, array: ProductInstance[]) => boolean): boolean;
|
|
72
|
+
/**
|
|
73
|
+
* Reduces the products array to a single value
|
|
74
|
+
* @param callback - Function to execute on each product
|
|
75
|
+
* @param initialValue - Initial value for the accumulator
|
|
76
|
+
* @returns The final accumulated value
|
|
77
|
+
*/
|
|
78
|
+
reduce<T>(callback: (accumulator: T, product: ProductInstance, index: number, array: ProductInstance[]) => T, initialValue: T): T;
|
|
79
|
+
/**
|
|
80
|
+
* Makes the instance iterable
|
|
81
|
+
* @returns Iterator for the products array
|
|
82
|
+
*/
|
|
83
|
+
[Symbol.iterator](): Iterator<ProductInstance>;
|
|
26
84
|
/**
|
|
27
85
|
* Custom toJSON method to control what gets serialized when logging
|
|
28
86
|
* @returns Serialized products and pagination data
|
|
@@ -2,6 +2,7 @@ import ProductInstance from "./product.instance.js";
|
|
|
2
2
|
/**
|
|
3
3
|
* Product pagination instance class providing a fluent API for paginated product results
|
|
4
4
|
* Provides methods for navigating through pages of products
|
|
5
|
+
* Supports array methods like map, filter, forEach for direct iteration
|
|
5
6
|
*/
|
|
6
7
|
export default class ProductPaginationInstance {
|
|
7
8
|
/**
|
|
@@ -29,6 +30,83 @@ export default class ProductPaginationInstance {
|
|
|
29
30
|
configurable: true
|
|
30
31
|
});
|
|
31
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Returns the number of products in the current page
|
|
35
|
+
*/
|
|
36
|
+
get length() {
|
|
37
|
+
return this.products.length;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Maps over the products array
|
|
41
|
+
* @param callback - Function to execute for each product
|
|
42
|
+
* @returns Array of mapped results
|
|
43
|
+
*/
|
|
44
|
+
map(callback) {
|
|
45
|
+
return this.products.map(callback);
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Filters the products array
|
|
49
|
+
* @param callback - Function to test each product
|
|
50
|
+
* @returns Array of products that pass the test
|
|
51
|
+
*/
|
|
52
|
+
filter(callback) {
|
|
53
|
+
return this.products.filter(callback);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Executes a function for each product
|
|
57
|
+
* @param callback - Function to execute for each product
|
|
58
|
+
*/
|
|
59
|
+
forEach(callback) {
|
|
60
|
+
this.products.forEach(callback);
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Finds the first product that satisfies the test
|
|
64
|
+
* @param callback - Function to test each product
|
|
65
|
+
* @returns The first product that passes the test, or undefined
|
|
66
|
+
*/
|
|
67
|
+
find(callback) {
|
|
68
|
+
return this.products.find(callback);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Finds the index of the first product that satisfies the test
|
|
72
|
+
* @param callback - Function to test each product
|
|
73
|
+
* @returns The index of the first product that passes the test, or -1
|
|
74
|
+
*/
|
|
75
|
+
findIndex(callback) {
|
|
76
|
+
return this.products.findIndex(callback);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Checks if some products satisfy the test
|
|
80
|
+
* @param callback - Function to test each product
|
|
81
|
+
* @returns true if at least one product passes the test
|
|
82
|
+
*/
|
|
83
|
+
some(callback) {
|
|
84
|
+
return this.products.some(callback);
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Checks if all products satisfy the test
|
|
88
|
+
* @param callback - Function to test each product
|
|
89
|
+
* @returns true if all products pass the test
|
|
90
|
+
*/
|
|
91
|
+
every(callback) {
|
|
92
|
+
return this.products.every(callback);
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Reduces the products array to a single value
|
|
96
|
+
* @param callback - Function to execute on each product
|
|
97
|
+
* @param initialValue - Initial value for the accumulator
|
|
98
|
+
* @returns The final accumulated value
|
|
99
|
+
*/
|
|
100
|
+
reduce(callback, initialValue) {
|
|
101
|
+
return this.products.reduce(callback, initialValue);
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Makes the instance iterable
|
|
105
|
+
* @returns Iterator for the products array
|
|
106
|
+
*/
|
|
107
|
+
[Symbol.iterator]() {
|
|
108
|
+
return this.products[Symbol.iterator]();
|
|
109
|
+
}
|
|
32
110
|
/**
|
|
33
111
|
* Custom toJSON method to control what gets serialized when logging
|
|
34
112
|
* @returns Serialized products and pagination data
|