lua-cli 2.1.0-alpha.6 → 2.2.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/README.md CHANGED
@@ -195,7 +195,7 @@ This command will:
195
195
  - Available at `http://localhost:3000` (opens automatically)
196
196
  - **Live Log Panel**:
197
197
  - Real-time log feed showing execution details
198
- - WebSocket connection to `wss://api.lua.dev/feed`
198
+ - WebSocket connection to `wss://api.heylua.ai/feed`
199
199
  - Console-style interface with color-coded log levels
200
200
  - Shows tool calls, errors, metrics, and execution metadata
201
201
  - Displays detailed information in expandable sections
@@ -498,7 +498,7 @@ For more details, see [USER_DATA_API.md](./USER_DATA_API.md).
498
498
 
499
499
  For support and questions:
500
500
  - Create an issue on [GitHub](https://github.com/lua-ai-global/lua-cli/issues)
501
- - Contact: stefan@lua.dev
501
+ - Contact: stefan@heylua.ai
502
502
 
503
503
  ## Changelog
504
504
 
@@ -227,7 +227,7 @@ async function bundleTool(tool, distDir) {
227
227
  platform: 'node',
228
228
  target: 'node16',
229
229
  outfile: outputPath,
230
- external: ['lua-cli/skill', 'lua-cli/user-data-api', 'zod'], // Exclude lua-cli modules and zod - injected into VM
230
+ external: ['lua-cli/skill', 'lua-cli/user-data-api', 'lua-cli/product-api', 'lua-cli/custom-data-api', 'zod', 'keytar', 'esbuild', 'commander', 'inquirer', 'node-fetch', 'ws', 'socket.io-client', 'ts-morph'], // Exclude lua-cli modules, zod, and native modules
231
231
  minify: true, // Minify for smaller file sizes
232
232
  sourcemap: false,
233
233
  resolveExtensions: ['.ts', '.js', '.json'],
@@ -272,6 +272,56 @@ async function wrapToolForVM(outputPath, tool) {
272
272
  }
273
273
  }
274
274
  };
275
+
276
+ // Mock lua-cli/product-api module
277
+ const luaCliProductApi = {
278
+ product: typeof product !== 'undefined' ? product : {
279
+ data: {
280
+ get: async (page = 1, limit = 10) => ({ success: true, data: [], pagination: { currentPage: page, totalPages: 1, totalCount: 0, limit, hasNextPage: false, hasPrevPage: false, nextPage: null, prevPage: null } }),
281
+ update: async (data, productId) => ({ updated: true, isNew: false, product: data }),
282
+ create: async (data) => ({ updated: false, isNew: true, product: data }),
283
+ delete: async (productId) => ({ deleted: true }),
284
+ search: async (searchQuery) => ({ success: true, message: \`Found 0 products for "\${searchQuery}"\`, data: [] })
285
+ }
286
+ }
287
+ };
288
+
289
+ // Mock lua-cli/custom-data-api module
290
+ const luaCliCustomDataApi = {
291
+ customData: typeof customData !== 'undefined' ? customData : {
292
+ create: async (collectionName, data) => ({
293
+ id: 'mock-id-' + Date.now(),
294
+ data: data.data,
295
+ createdAt: Date.now(),
296
+ updatedAt: Date.now(),
297
+ searchText: data.searchText
298
+ }),
299
+ get: async (collectionName, filter, page = 1, limit = 10) => ({
300
+ data: [],
301
+ pagination: {
302
+ currentPage: page,
303
+ totalPages: 1,
304
+ totalCount: 0,
305
+ limit,
306
+ hasNextPage: false,
307
+ hasPrevPage: false
308
+ }
309
+ }),
310
+ getEntry: async (collectionName, entryId) => null,
311
+ update: async (collectionName, entryId, data) => ({
312
+ status: 'success',
313
+ message: 'Custom data entry updated'
314
+ }),
315
+ search: async (collectionName, searchText, limit = 10, scoreThreshold = 0.6) => ({
316
+ data: [],
317
+ count: 0
318
+ }),
319
+ delete: async (collectionName, entryId) => ({
320
+ status: 'success',
321
+ message: 'Custom data entry deleted'
322
+ })
323
+ }
324
+ };
275
325
 
276
326
  // Mock zod module
277
327
  const zodModule = (() => {
@@ -313,6 +363,12 @@ async function wrapToolForVM(outputPath, tool) {
313
363
  if (id === 'lua-cli/user-data-api') {
314
364
  return luaCliUserDataApi;
315
365
  }
366
+ if (id === 'lua-cli/product-api') {
367
+ return luaCliProductApi;
368
+ }
369
+ if (id === 'lua-cli/custom-data-api') {
370
+ return luaCliCustomDataApi;
371
+ }
316
372
  if (id === 'zod') {
317
373
  return zodModule;
318
374
  }
@@ -344,7 +400,7 @@ async function bundleMainIndex(indexPath, distDir) {
344
400
  platform: 'node',
345
401
  target: 'node16',
346
402
  outfile: path.join(distDir, 'index.js'),
347
- external: ['lua-cli/skill', 'lua-cli/user-data-api', 'zod'], // Exclude lua-cli modules and zod
403
+ external: ['lua-cli/skill', 'lua-cli/user-data-api', 'lua-cli/product-api', 'lua-cli/custom-data-api', 'zod', 'keytar', 'esbuild', 'commander', 'inquirer', 'node-fetch', 'ws', 'socket.io-client', 'ts-morph'], // Exclude lua-cli modules, zod, and native modules
348
404
  minify: true, // Minify for smaller file sizes
349
405
  sourcemap: false,
350
406
  resolveExtensions: ['.ts', '.js', '.json'],
@@ -0,0 +1,72 @@
1
+ export interface CustomDataEntry {
2
+ id: string;
3
+ data: any;
4
+ createdAt: number;
5
+ updatedAt: number;
6
+ searchText?: string;
7
+ }
8
+ export interface CreateCustomDataRequest {
9
+ data: any;
10
+ searchText?: string;
11
+ }
12
+ export interface CreateCustomDataResponse {
13
+ id: string;
14
+ data: any;
15
+ createdAt: number;
16
+ updatedAt: number;
17
+ searchText?: string;
18
+ }
19
+ export interface GetCustomDataResponse {
20
+ data: CustomDataEntry[];
21
+ pagination: {
22
+ currentPage: number;
23
+ totalPages: number;
24
+ totalCount: number;
25
+ limit: number;
26
+ hasNextPage: boolean;
27
+ hasPrevPage: boolean;
28
+ };
29
+ }
30
+ export interface UpdateCustomDataRequest {
31
+ data: any;
32
+ searchText?: string;
33
+ }
34
+ export interface UpdateCustomDataResponse {
35
+ status: string;
36
+ message: string;
37
+ }
38
+ export interface SearchCustomDataResponse {
39
+ data: Array<CustomDataEntry & {
40
+ score: number;
41
+ }>;
42
+ count: number;
43
+ }
44
+ export interface DeleteCustomDataResponse {
45
+ status: string;
46
+ message: string;
47
+ }
48
+ export declare class CustomDataAPI {
49
+ private collections;
50
+ constructor();
51
+ private generateId;
52
+ private getCollection;
53
+ create(collectionName: string, data: CreateCustomDataRequest): Promise<CreateCustomDataResponse>;
54
+ get(collectionName: string, filter?: any, page?: number, limit?: number): Promise<GetCustomDataResponse>;
55
+ getEntry(collectionName: string, entryId: string): Promise<CustomDataEntry | null>;
56
+ update(collectionName: string, entryId: string, data: UpdateCustomDataRequest): Promise<UpdateCustomDataResponse>;
57
+ search(collectionName: string, searchText: string, limit?: number, scoreThreshold?: number): Promise<SearchCustomDataResponse>;
58
+ delete(collectionName: string, entryId: string): Promise<DeleteCustomDataResponse>;
59
+ private matchesFilter;
60
+ private calculateSimilarity;
61
+ getAllCollections(): Map<string, CustomDataEntry[]>;
62
+ clearCollection(collectionName: string): void;
63
+ clearAllCollections(): void;
64
+ }
65
+ export declare const customData: {
66
+ create: (collectionName: string, data: CreateCustomDataRequest) => Promise<CreateCustomDataResponse>;
67
+ get: (collectionName: string, filter?: any, page?: number, limit?: number) => Promise<GetCustomDataResponse>;
68
+ getEntry: (collectionName: string, entryId: string) => Promise<CustomDataEntry | null>;
69
+ update: (collectionName: string, entryId: string, data: UpdateCustomDataRequest) => Promise<UpdateCustomDataResponse>;
70
+ search: (collectionName: string, searchText: string, limit?: number, scoreThreshold?: number) => Promise<SearchCustomDataResponse>;
71
+ delete: (collectionName: string, entryId: string) => Promise<DeleteCustomDataResponse>;
72
+ };
@@ -0,0 +1,174 @@
1
+ export class CustomDataAPI {
2
+ constructor() {
3
+ // Store data by collection name
4
+ this.collections = new Map();
5
+ }
6
+ generateId() {
7
+ return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
8
+ const r = Math.random() * 16 | 0;
9
+ const v = c == 'x' ? r : (r & 0x3 | 0x8);
10
+ return v.toString(16);
11
+ });
12
+ }
13
+ getCollection(collectionName) {
14
+ if (!this.collections.has(collectionName)) {
15
+ this.collections.set(collectionName, []);
16
+ }
17
+ return this.collections.get(collectionName);
18
+ }
19
+ async create(collectionName, data) {
20
+ const collection = this.getCollection(collectionName);
21
+ const now = Date.now();
22
+ const entry = {
23
+ id: this.generateId(),
24
+ data: data.data,
25
+ createdAt: now,
26
+ updatedAt: now,
27
+ searchText: data.searchText
28
+ };
29
+ collection.push(entry);
30
+ return {
31
+ id: entry.id,
32
+ data: entry.data,
33
+ createdAt: entry.createdAt,
34
+ updatedAt: entry.updatedAt,
35
+ searchText: entry.searchText
36
+ };
37
+ }
38
+ async get(collectionName, filter, page = 1, limit = 10) {
39
+ const collection = this.getCollection(collectionName);
40
+ let filteredData = [...collection];
41
+ // Apply filter if provided
42
+ if (filter) {
43
+ filteredData = collection.filter(entry => {
44
+ return this.matchesFilter(entry.data, filter);
45
+ });
46
+ }
47
+ // Apply pagination
48
+ const startIndex = (page - 1) * limit;
49
+ const endIndex = startIndex + limit;
50
+ const paginatedData = filteredData.slice(startIndex, endIndex);
51
+ const totalCount = filteredData.length;
52
+ const totalPages = Math.ceil(totalCount / limit);
53
+ return {
54
+ data: paginatedData,
55
+ pagination: {
56
+ currentPage: page,
57
+ totalPages: totalPages,
58
+ totalCount: totalCount,
59
+ limit: limit,
60
+ hasNextPage: page < totalPages,
61
+ hasPrevPage: page > 1
62
+ }
63
+ };
64
+ }
65
+ async getEntry(collectionName, entryId) {
66
+ const collection = this.getCollection(collectionName);
67
+ return collection.find(entry => entry.id === entryId) || null;
68
+ }
69
+ async update(collectionName, entryId, data) {
70
+ const collection = this.getCollection(collectionName);
71
+ const entryIndex = collection.findIndex(entry => entry.id === entryId);
72
+ if (entryIndex === -1) {
73
+ return {
74
+ status: 'error',
75
+ message: 'Custom data entry not found'
76
+ };
77
+ }
78
+ const entry = collection[entryIndex];
79
+ entry.data = { ...entry.data, ...data.data };
80
+ entry.updatedAt = Date.now();
81
+ if (data.searchText !== undefined) {
82
+ entry.searchText = data.searchText;
83
+ }
84
+ return {
85
+ status: 'success',
86
+ message: 'Custom data entry updated'
87
+ };
88
+ }
89
+ async search(collectionName, searchText, limit = 10, scoreThreshold = 0.6) {
90
+ const collection = this.getCollection(collectionName);
91
+ const results = [];
92
+ for (const entry of collection) {
93
+ if (entry.searchText) {
94
+ const score = this.calculateSimilarity(searchText.toLowerCase(), entry.searchText.toLowerCase());
95
+ if (score >= scoreThreshold) {
96
+ results.push({ ...entry, score });
97
+ }
98
+ }
99
+ }
100
+ // Sort by score descending
101
+ results.sort((a, b) => b.score - a.score);
102
+ // Apply limit
103
+ const limitedResults = results.slice(0, limit);
104
+ return {
105
+ data: limitedResults,
106
+ count: limitedResults.length
107
+ };
108
+ }
109
+ async delete(collectionName, entryId) {
110
+ const collection = this.getCollection(collectionName);
111
+ const initialLength = collection.length;
112
+ const updatedCollection = collection.filter(entry => entry.id !== entryId);
113
+ this.collections.set(collectionName, updatedCollection);
114
+ if (updatedCollection.length < initialLength) {
115
+ return {
116
+ status: 'success',
117
+ message: 'Custom data entry deleted'
118
+ };
119
+ }
120
+ else {
121
+ return {
122
+ status: 'error',
123
+ message: 'Custom data entry not found'
124
+ };
125
+ }
126
+ }
127
+ // Helper method to check if an object matches a filter
128
+ matchesFilter(obj, filter) {
129
+ for (const key in filter) {
130
+ if (filter.hasOwnProperty(key)) {
131
+ if (typeof filter[key] === 'object' && filter[key] !== null) {
132
+ if (typeof obj[key] !== 'object' || !this.matchesFilter(obj[key], filter[key])) {
133
+ return false;
134
+ }
135
+ }
136
+ else {
137
+ if (obj[key] !== filter[key]) {
138
+ return false;
139
+ }
140
+ }
141
+ }
142
+ }
143
+ return true;
144
+ }
145
+ // Simple similarity calculation (Jaccard similarity for words)
146
+ calculateSimilarity(str1, str2) {
147
+ const words1 = new Set(str1.split(/\s+/));
148
+ const words2 = new Set(str2.split(/\s+/));
149
+ const intersection = new Set([...words1].filter(x => words2.has(x)));
150
+ const union = new Set([...words1, ...words2]);
151
+ return intersection.size / union.size;
152
+ }
153
+ // Method to get all collections (for debugging/testing)
154
+ getAllCollections() {
155
+ return this.collections;
156
+ }
157
+ // Method to clear a collection (for testing)
158
+ clearCollection(collectionName) {
159
+ this.collections.set(collectionName, []);
160
+ }
161
+ // Method to clear all collections (for testing)
162
+ clearAllCollections() {
163
+ this.collections.clear();
164
+ }
165
+ }
166
+ const customDataAPI = new CustomDataAPI();
167
+ export const customData = {
168
+ create: (collectionName, data) => customDataAPI.create(collectionName, data),
169
+ get: (collectionName, filter, page, limit) => customDataAPI.get(collectionName, filter, page, limit),
170
+ getEntry: (collectionName, entryId) => customDataAPI.getEntry(collectionName, entryId),
171
+ update: (collectionName, entryId, data) => customDataAPI.update(collectionName, entryId, data),
172
+ search: (collectionName, searchText, limit, scoreThreshold) => customDataAPI.search(collectionName, searchText, limit, scoreThreshold),
173
+ delete: (collectionName, entryId) => customDataAPI.delete(collectionName, entryId),
174
+ };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  #!/usr/bin/env node
2
2
  export { user, UserDataAPI } from './user-data-api.js';
3
3
  export { product, ProductAPI } from './product-api.js';
4
+ export { customData, CustomDataAPI } from './custom-data-api.js';
package/dist/index.js CHANGED
@@ -46,3 +46,4 @@ program.parse(process.argv);
46
46
  // Export user data API for use in projects
47
47
  export { user, UserDataAPI } from './user-data-api.js';
48
48
  export { product, ProductAPI } from './product-api.js';
49
+ export { customData, CustomDataAPI } from './custom-data-api.js';
@@ -34,15 +34,156 @@ export interface SearchProductsResponse {
34
34
  message: string;
35
35
  data: Product[];
36
36
  }
37
+ export interface BasketItem {
38
+ id: string;
39
+ price: number;
40
+ quantity: number;
41
+ SKU?: string;
42
+ addedAt?: string;
43
+ [key: string]: any;
44
+ }
45
+ export interface Basket {
46
+ id: string;
47
+ userId: string;
48
+ agentId: string;
49
+ data: {
50
+ currency: string;
51
+ items: BasketItem[];
52
+ createdAt: string;
53
+ };
54
+ common: {
55
+ status: 'active' | 'checked_out' | 'abandoned' | 'expired';
56
+ totalAmount: string | number;
57
+ itemCount: number;
58
+ };
59
+ createdAt: string;
60
+ updatedAt: string;
61
+ __v: number;
62
+ }
63
+ export interface CreateBasketRequest {
64
+ currency: string;
65
+ }
66
+ export interface CreateBasketResponse {
67
+ success: boolean;
68
+ message: string;
69
+ data: Basket;
70
+ }
71
+ export interface GetBasketsResponse {
72
+ success: boolean;
73
+ message: string;
74
+ data: Basket[];
75
+ }
76
+ export interface AddItemToBasketRequest {
77
+ id: string;
78
+ price: number;
79
+ quantity: number;
80
+ [key: string]: any;
81
+ }
82
+ export interface AddItemToBasketResponse {
83
+ success: boolean;
84
+ message: string;
85
+ data: Basket;
86
+ }
87
+ export interface RemoveItemFromBasketResponse {
88
+ success: boolean;
89
+ message: string;
90
+ data: Basket;
91
+ }
92
+ export interface ClearBasketResponse {
93
+ success: boolean;
94
+ message: string;
95
+ data: Basket;
96
+ }
97
+ export interface UpdateBasketStatusResponse {
98
+ success: boolean;
99
+ message: string;
100
+ data: Basket;
101
+ }
102
+ export interface Order {
103
+ id: string;
104
+ userId: string;
105
+ agentId: string;
106
+ orderId: string;
107
+ data: {
108
+ currency: string;
109
+ items: BasketItem[];
110
+ createdAt: string;
111
+ basketId: string;
112
+ orderDate: string;
113
+ orderId: string;
114
+ [key: string]: any;
115
+ };
116
+ common: {
117
+ status: 'pending' | 'confirmed' | 'fulfilled' | 'cancelled';
118
+ totalAmount: string | number;
119
+ currency: string;
120
+ itemCount: number;
121
+ };
122
+ createdAt: string;
123
+ updatedAt: string;
124
+ __v: number;
125
+ }
126
+ export interface CreateOrderRequest {
127
+ basketId: string;
128
+ data: {
129
+ [key: string]: any;
130
+ };
131
+ }
132
+ export interface CreateOrderResponse {
133
+ success: boolean;
134
+ message: string;
135
+ data: Order;
136
+ }
137
+ export interface UpdateOrderStatusResponse {
138
+ success: boolean;
139
+ message: string;
140
+ data: Order;
141
+ }
142
+ export interface GetUserOrdersResponse {
143
+ success: boolean;
144
+ message: string;
145
+ data: Order[];
146
+ }
147
+ export type BasketStatus = 'active' | 'checked_out' | 'abandoned' | 'expired';
148
+ export type OrderStatus = 'pending' | 'confirmed' | 'fulfilled' | 'cancelled';
37
149
  export declare class ProductAPI {
38
- products: any;
150
+ products: Product[];
151
+ baskets: Basket[];
152
+ orders: Order[];
39
153
  constructor();
40
154
  get(page?: number, limit?: number): Promise<ProductsResponse>;
41
155
  create(data: Record<string, any>): Promise<CreateProductResponse>;
42
156
  update(data: Record<string, any>, productId: string): Promise<UpdateProductResponse>;
43
157
  delete(productId: string): Promise<DeleteProductResponse>;
44
158
  search(searchQuery: string): Promise<SearchProductsResponse>;
159
+ createBasket(data: CreateBasketRequest): Promise<CreateBasketResponse>;
160
+ getBaskets(status?: BasketStatus): Promise<GetBasketsResponse>;
161
+ addItemToBasket(basketId: string, data: AddItemToBasketRequest): Promise<AddItemToBasketResponse>;
162
+ removeItemFromBasket(basketId: string, itemId: string): Promise<RemoveItemFromBasketResponse>;
163
+ clearBasket(basketId: string): Promise<ClearBasketResponse>;
164
+ updateBasketStatus(basketId: string, status: BasketStatus): Promise<UpdateBasketStatusResponse>;
165
+ createOrder(data: CreateOrderRequest): Promise<CreateOrderResponse>;
166
+ updateOrderStatus(orderId: string, status: OrderStatus): Promise<UpdateOrderStatusResponse>;
167
+ getUserOrders(userId: string): Promise<GetUserOrdersResponse>;
45
168
  }
46
169
  export declare const product: {
170
+ create: (data: Record<string, any>) => Promise<CreateProductResponse>;
171
+ get: (page?: number, limit?: number) => Promise<ProductsResponse>;
172
+ update: (data: Record<string, any>, productId: string) => Promise<UpdateProductResponse>;
173
+ delete: (productId: string) => Promise<DeleteProductResponse>;
174
+ search: (searchQuery: string) => Promise<SearchProductsResponse>;
47
175
  data: ProductAPI;
176
+ basket: {
177
+ create: (data: CreateBasketRequest) => Promise<CreateBasketResponse>;
178
+ get: (status?: BasketStatus) => Promise<GetBasketsResponse>;
179
+ addItem: (basketId: string, data: AddItemToBasketRequest) => Promise<AddItemToBasketResponse>;
180
+ removeItem: (basketId: string, itemId: string) => Promise<RemoveItemFromBasketResponse>;
181
+ clear: (basketId: string) => Promise<ClearBasketResponse>;
182
+ updateStatus: (basketId: string, status: BasketStatus) => Promise<UpdateBasketStatusResponse>;
183
+ };
184
+ order: {
185
+ create: (data: CreateOrderRequest) => Promise<CreateOrderResponse>;
186
+ updateStatus: (orderId: string, status: OrderStatus) => Promise<UpdateOrderStatusResponse>;
187
+ get: (userId: string) => Promise<GetUserOrdersResponse>;
188
+ };
48
189
  };
@@ -1,27 +1,141 @@
1
1
  export class ProductAPI {
2
2
  constructor() {
3
- this.products = {};
3
+ this.products = [];
4
+ this.baskets = [];
5
+ this.orders = [];
4
6
  }
5
7
  async get(page = 1, limit = 10) {
6
- return { success: true, data: this.products, pagination: { currentPage: page, totalPages: 1, totalCount: this.products.length, limit: limit, hasNextPage: false, hasPrevPage: false, nextPage: null, prevPage: null } };
8
+ return {
9
+ success: true,
10
+ data: this.products,
11
+ pagination: {
12
+ currentPage: page,
13
+ totalPages: 1,
14
+ totalCount: this.products.length,
15
+ limit: limit,
16
+ hasNextPage: false,
17
+ hasPrevPage: false,
18
+ nextPage: null,
19
+ prevPage: null
20
+ }
21
+ };
7
22
  }
8
23
  async create(data) {
9
- this.products = data;
10
- return { updated: true, isNew: true, product: this.products };
24
+ const product = data;
25
+ const existingIndex = this.products.findIndex(p => p.id === product.id);
26
+ if (existingIndex >= 0) {
27
+ this.products[existingIndex] = product;
28
+ return { updated: true, isNew: false, product };
29
+ }
30
+ else {
31
+ this.products.push(product);
32
+ return { updated: false, isNew: true, product };
33
+ }
11
34
  }
12
35
  async update(data, productId) {
13
- // Update is the same as create for this API
14
- this.products = { ...this.products, ...data };
15
- return { updated: true, isNew: false, product: this.products };
36
+ const product = data;
37
+ const existingIndex = this.products.findIndex(p => p.id === productId);
38
+ if (existingIndex >= 0) {
39
+ this.products[existingIndex] = { ...this.products[existingIndex], ...product };
40
+ return { updated: true, isNew: false, product: this.products[existingIndex] };
41
+ }
42
+ else {
43
+ this.products.push(product);
44
+ return { updated: false, isNew: true, product };
45
+ }
16
46
  }
17
47
  async delete(productId) {
48
+ const initialLength = this.products.length;
18
49
  this.products = this.products.filter((product) => product.id !== productId);
19
- return { deleted: true };
50
+ return { deleted: this.products.length < initialLength };
20
51
  }
21
52
  async search(searchQuery) {
22
- return { success: true, message: 'Products searched successfully', data: this.products };
53
+ const results = this.products.filter(product => Object.values(product).some(value => String(value).toLowerCase().includes(searchQuery.toLowerCase())));
54
+ return {
55
+ success: true,
56
+ message: `Successfully found ${results.length} products for "${searchQuery}"`,
57
+ data: results
58
+ };
59
+ }
60
+ async createBasket(data) {
61
+ const basket = { ...data, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), __v: 0 };
62
+ this.baskets.push(basket);
63
+ return { success: true, message: 'Basket created successfully', data: basket };
64
+ }
65
+ async getBaskets(status) {
66
+ if (status) {
67
+ return { success: true, message: 'Baskets fetched successfully', data: this.baskets.filter((basket) => basket.common.status === status) };
68
+ }
69
+ return { success: true, message: 'Baskets fetched successfully', data: this.baskets };
70
+ }
71
+ async addItemToBasket(basketId, data) {
72
+ const basket = this.baskets.find((basket) => basket.id === basketId);
73
+ if (basket) {
74
+ basket.data.items.push(data);
75
+ return { success: true, message: 'Item added to basket successfully', data: basket };
76
+ }
77
+ return { success: false, message: 'Basket not found', data: null };
78
+ }
79
+ async removeItemFromBasket(basketId, itemId) {
80
+ const basket = this.baskets.find((basket) => basket.id === basketId);
81
+ if (basket) {
82
+ basket.data.items = basket.data.items.filter((item) => item.id !== itemId);
83
+ return { success: true, message: 'Item removed from basket successfully', data: basket };
84
+ }
85
+ return { success: false, message: 'Basket not found', data: null };
86
+ }
87
+ async clearBasket(basketId) {
88
+ const basket = this.baskets.find((basket) => basket.id === basketId);
89
+ if (basket) {
90
+ basket.data.items = [];
91
+ return { success: true, message: 'Basket cleared successfully', data: basket };
92
+ }
93
+ return { success: false, message: 'Basket not found', data: null };
94
+ }
95
+ async updateBasketStatus(basketId, status) {
96
+ const basket = this.baskets.find((basket) => basket.id === basketId);
97
+ if (basket) {
98
+ basket.common.status = status;
99
+ return { success: true, message: 'Basket status updated successfully', data: basket };
100
+ }
101
+ return { success: false, message: 'Basket not found', data: null };
102
+ }
103
+ async createOrder(data) {
104
+ const order = { ...data, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), __v: 0 };
105
+ this.orders.push(order);
106
+ return { success: true, message: 'Order created successfully', data: order };
107
+ }
108
+ async updateOrderStatus(orderId, status) {
109
+ const order = this.orders.find((order) => order.id === orderId);
110
+ if (order) {
111
+ order.common.status = status;
112
+ return { success: true, message: 'Order status updated successfully', data: order };
113
+ }
114
+ return { success: false, message: 'Order not found', data: null };
115
+ }
116
+ async getUserOrders(userId) {
117
+ return { success: true, message: 'User orders fetched successfully', data: this.orders.filter((order) => order.userId === userId) };
23
118
  }
24
119
  }
120
+ const productAPI = new ProductAPI();
25
121
  export const product = {
26
- data: new ProductAPI()
122
+ create: productAPI.create,
123
+ get: productAPI.get,
124
+ update: productAPI.update,
125
+ delete: productAPI.delete,
126
+ search: productAPI.search,
127
+ data: productAPI,
128
+ basket: {
129
+ create: productAPI.createBasket,
130
+ get: productAPI.getBaskets,
131
+ addItem: productAPI.addItemToBasket,
132
+ removeItem: productAPI.removeItemFromBasket,
133
+ clear: productAPI.clearBasket,
134
+ updateStatus: productAPI.updateBasketStatus
135
+ },
136
+ order: {
137
+ create: productAPI.createOrder,
138
+ updateStatus: productAPI.updateOrderStatus,
139
+ get: productAPI.getUserOrders
140
+ }
27
141
  };