get-fake-api 0.0.0-stage → 1.0.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/data/orders.js ADDED
@@ -0,0 +1,137 @@
1
+ const baseOrders = [
2
+ {
3
+ id: 1,
4
+ orderNumber: "ORD-2026-9041",
5
+ userId: 1,
6
+ items: [
7
+ { productId: 1, title: "Pro Wireless Noise-Cancelling Headphones", price: 299.99, quantity: 1, total: 299.99 },
8
+ { productId: 3, title: "Minimalist Mechanical Keyboard RGB", price: 139.50, quantity: 1, total: 139.50 }
9
+ ],
10
+ totalAmount: 439.49,
11
+ currency: "USD",
12
+ paymentMethod: "credit_card",
13
+ status: "delivered",
14
+ trackingNumber: "TRK-9812-US",
15
+ createdAt: "2026-10-01T09:14:00Z"
16
+ },
17
+ {
18
+ id: 2,
19
+ orderNumber: "ORD-2026-9042",
20
+ userId: 2,
21
+ items: [
22
+ { productId: 4, title: "TitanBook 16-inch M-Pro Laptop", price: 1899.99, quantity: 1, total: 1899.99 }
23
+ ],
24
+ totalAmount: 1899.99,
25
+ currency: "USD",
26
+ paymentMethod: "apple_pay",
27
+ status: "shipped",
28
+ trackingNumber: "TRK-9813-US",
29
+ createdAt: "2026-10-08T15:22:00Z"
30
+ },
31
+ {
32
+ id: 3,
33
+ orderNumber: "ORD-2026-9043",
34
+ userId: 3,
35
+ items: [
36
+ { productId: 6, title: "Nordic Minimalist Ceramic Desk Lamp", price: 79.90, quantity: 2, total: 159.80 },
37
+ { productId: 5, title: "Artisan Roasted Single-Origin Coffee Beans (1kg)", price: 34.00, quantity: 1, total: 34.00 }
38
+ ],
39
+ totalAmount: 193.80,
40
+ currency: "USD",
41
+ paymentMethod: "paypal",
42
+ status: "processing",
43
+ trackingNumber: "TRK-9814-UK",
44
+ createdAt: "2026-10-12T11:45:00Z"
45
+ },
46
+ {
47
+ id: 4,
48
+ orderNumber: "ORD-2026-9044",
49
+ userId: 4,
50
+ items: [
51
+ { productId: 8, title: "Clean Code & System Design Handbook", price: 49.99, quantity: 1, total: 49.99 }
52
+ ],
53
+ totalAmount: 49.99,
54
+ currency: "USD",
55
+ paymentMethod: "credit_card",
56
+ status: "pending",
57
+ trackingNumber: null,
58
+ createdAt: "2026-10-15T18:05:00Z"
59
+ }
60
+ ];
61
+
62
+ const paymentMethods = ["credit_card", "paypal", "apple_pay", "stripe"];
63
+ const orderStatuses = ["pending", "processing", "shipped", "delivered", "cancelled"];
64
+
65
+ function generateOrder(id) {
66
+ const status = orderStatuses[id % orderStatuses.length];
67
+ const paymentMethod = paymentMethods[id % paymentMethods.length];
68
+ const qty = 1 + (id % 3);
69
+ const price = Number((25.00 + (id * 19.5) % 300).toFixed(2));
70
+ const total = Number((price * qty).toFixed(2));
71
+
72
+ return {
73
+ id,
74
+ orderNumber: `ORD-2026-${9000 + id}`,
75
+ userId: 1 + (id % 10),
76
+ items: [
77
+ {
78
+ productId: 1 + (id % 10),
79
+ title: `Product Item #${1 + (id % 10)}`,
80
+ price,
81
+ quantity: qty,
82
+ total
83
+ }
84
+ ],
85
+ totalAmount: total,
86
+ currency: "USD",
87
+ paymentMethod,
88
+ status,
89
+ trackingNumber: status === "pending" || status === "cancelled" ? null : `TRK-${1000 + id}-GL`,
90
+ createdAt: new Date(Date.now() - id * 43200000).toISOString()
91
+ };
92
+ }
93
+
94
+ function getOrders(optionsOrCount) {
95
+ let count = 4;
96
+ let filters = {};
97
+
98
+ if (typeof optionsOrCount === "number") {
99
+ count = optionsOrCount <= 0 ? 0 : optionsOrCount;
100
+ } else if (typeof optionsOrCount === "object" && optionsOrCount !== null) {
101
+ if (typeof optionsOrCount.count === "number") count = optionsOrCount.count;
102
+ else if (typeof optionsOrCount.limit === "number") count = optionsOrCount.limit;
103
+ filters = optionsOrCount;
104
+ }
105
+
106
+ const result = [];
107
+ const targetCount = count > 0 ? count : 0;
108
+ const poolSize = Math.max(targetCount, baseOrders.length);
109
+
110
+ for (let i = 0; i < poolSize; i++) {
111
+ const order = i < baseOrders.length ? baseOrders[i] : generateOrder(i + 1);
112
+
113
+ if (filters.status && order.status.toLowerCase() !== filters.status.toLowerCase()) continue;
114
+ if (filters.userId && order.userId !== Number(filters.userId)) continue;
115
+ if (filters.paymentMethod && order.paymentMethod.toLowerCase() !== filters.paymentMethod.toLowerCase()) continue;
116
+
117
+ result.push(order);
118
+ if (result.length >= targetCount) break;
119
+ }
120
+
121
+ return result;
122
+ }
123
+
124
+ function getOrderById(id) {
125
+ const numericId = Number(id);
126
+ if (!numericId || numericId <= 0) return null;
127
+ if (numericId <= baseOrders.length) {
128
+ return baseOrders.find(o => o.id === numericId) || null;
129
+ }
130
+ return generateOrder(numericId);
131
+ }
132
+
133
+ module.exports = {
134
+ getOrders,
135
+ getOrderById,
136
+ baseOrders
137
+ };
package/data/posts.js ADDED
@@ -0,0 +1,214 @@
1
+ const basePosts = [
2
+ {
3
+ id: 1,
4
+ userId: 1,
5
+ title: "Mastering Asynchronous JavaScript in Modern Web Apps",
6
+ body: "Promises and async/await have fundamentally transformed how JavaScript handles concurrency. Understanding microtasks, macrotasks, and the event loop is crucial for building performant user experiences.",
7
+ tags: ["javascript", "webdev", "programming"],
8
+ reactions: { likes: 142, dislikes: 3 },
9
+ views: 1250,
10
+ createdAt: "2026-09-12T10:30:00Z"
11
+ },
12
+ {
13
+ id: 2,
14
+ userId: 2,
15
+ title: "10 Principles for Crafting Clean API Contracts",
16
+ body: "Designing intuitive REST and GraphQL APIs starts with consistent error envelopes, predictable pagination structures, and semantic HTTP status codes.",
17
+ tags: ["api", "architecture", "backend"],
18
+ reactions: { likes: 218, dislikes: 5 },
19
+ views: 3410,
20
+ createdAt: "2026-09-15T14:20:00Z"
21
+ },
22
+ {
23
+ id: 3,
24
+ userId: 3,
25
+ title: "The Art of Micro-interactions in Design Systems",
26
+ body: "Micro-interactions provide sensory feedback that makes user interfaces feel tangible and alive. From subtle button spring animations to smooth page transitions, details define quality.",
27
+ tags: ["ui", "ux", "design"],
28
+ reactions: { likes: 95, dislikes: 1 },
29
+ views: 890,
30
+ createdAt: "2026-09-20T08:15:00Z"
31
+ },
32
+ {
33
+ id: 4,
34
+ userId: 4,
35
+ title: "Zero-Downtime Deployments with Docker and Kubernetes",
36
+ body: "Rolling updates and health check probes ensure your users never encounter 502 bad gateway errors during peak traffic releases.",
37
+ tags: ["devops", "docker", "cloud"],
38
+ reactions: { likes: 310, dislikes: 8 },
39
+ views: 4500,
40
+ createdAt: "2026-09-24T16:45:00Z"
41
+ },
42
+ {
43
+ id: 5,
44
+ userId: 5,
45
+ title: "Building Real-time Dashboards with WebSockets",
46
+ body: "Learn how to establish low-latency bidirectional connections between Node.js backends and browser frontends using native WebSockets.",
47
+ tags: ["nodejs", "realtime", "frontend"],
48
+ reactions: { likes: 178, dislikes: 4 },
49
+ views: 2100,
50
+ createdAt: "2026-10-01T11:00:00Z"
51
+ }
52
+ ];
53
+
54
+ const baseComments = [
55
+ {
56
+ id: 1,
57
+ postId: 1,
58
+ user: { id: 2, username: "johndoe", fullName: "John Doe" },
59
+ body: "Great explanation of the event loop! The microtask queue distinction cleared up a tricky bug I had.",
60
+ createdAt: "2026-09-12T11:45:00Z"
61
+ },
62
+ {
63
+ id: 2,
64
+ postId: 1,
65
+ user: { id: 4, username: "liamc", fullName: "Liam Chen" },
66
+ body: "Async/await with Promise.allSettled is a game changer for resilient error handling.",
67
+ createdAt: "2026-09-12T13:20:00Z"
68
+ },
69
+ {
70
+ id: 3,
71
+ postId: 2,
72
+ user: { id: 1, username: "sconnor", fullName: "Sarah Connor" },
73
+ body: "Standardizing error response schemas is honestly the #1 thing front-end engineers appreciate.",
74
+ createdAt: "2026-09-15T15:10:00Z"
75
+ },
76
+ {
77
+ id: 4,
78
+ postId: 3,
79
+ user: { id: 7, username: "cdubois", fullName: "Chloe Dubois" },
80
+ body: "Agreed! Even a 150ms spring transition gives the interface a delightful native feel.",
81
+ createdAt: "2026-09-20T09:30:00Z"
82
+ },
83
+ {
84
+ id: 5,
85
+ postId: 4,
86
+ user: { id: 8, username: "arjunp", fullName: "Arjun Patel" },
87
+ body: "Readiness probes combined with terminationGracePeriodSeconds is essential.",
88
+ createdAt: "2026-09-24T18:00:00Z"
89
+ }
90
+ ];
91
+
92
+ function generatePost(id) {
93
+ const titles = [
94
+ "Understanding State Management Patterns in 2026",
95
+ "Optimizing Core Web Vitals for Lightning-Fast Page Loads",
96
+ "How to Write Bulletproof Unit and Integration Tests",
97
+ "Securing JWT Authentication in Modern Single Page Apps",
98
+ "Exploring Edge Computing and Serverless Architecture"
99
+ ];
100
+ const tagsList = [
101
+ ["react", "state", "architecture"],
102
+ ["performance", "seo", "webdev"],
103
+ ["testing", "jest", "qa"],
104
+ ["security", "auth", "jwt"],
105
+ ["edge", "cloud", "serverless"]
106
+ ];
107
+
108
+ const index = id % titles.length;
109
+ return {
110
+ id,
111
+ userId: 1 + (id % 10),
112
+ title: `${titles[index]} (Part ${id})`,
113
+ body: `Deep dive exploration into architectural strategies and practical code samples for building robust applications. Article #${id}.`,
114
+ tags: tagsList[index],
115
+ reactions: { likes: 50 + (id * 19) % 300, dislikes: (id * 3) % 15 },
116
+ views: 400 + (id * 73) % 5000,
117
+ createdAt: new Date(Date.now() - id * 86400000).toISOString()
118
+ };
119
+ }
120
+
121
+ function generateComment(id) {
122
+ return {
123
+ id,
124
+ postId: 1 + (id % 5),
125
+ user: {
126
+ id: 1 + (id % 10),
127
+ username: `user_${id}`,
128
+ fullName: `User ${id}`
129
+ },
130
+ body: `Insightful post! Really enjoyed reading through section #${id % 4 + 1}.`,
131
+ createdAt: new Date(Date.now() - id * 3600000).toISOString()
132
+ };
133
+ }
134
+
135
+ function getPosts(optionsOrCount) {
136
+ let count = 5;
137
+ let filters = {};
138
+
139
+ if (typeof optionsOrCount === "number") {
140
+ count = optionsOrCount <= 0 ? 0 : optionsOrCount;
141
+ } else if (typeof optionsOrCount === "object" && optionsOrCount !== null) {
142
+ if (typeof optionsOrCount.count === "number") count = optionsOrCount.count;
143
+ else if (typeof optionsOrCount.limit === "number") count = optionsOrCount.limit;
144
+ filters = optionsOrCount;
145
+ }
146
+
147
+ const result = [];
148
+ const targetCount = count > 0 ? count : 0;
149
+ const poolSize = Math.max(targetCount, basePosts.length);
150
+
151
+ for (let i = 0; i < poolSize; i++) {
152
+ const post = i < basePosts.length ? basePosts[i] : generatePost(i + 1);
153
+
154
+ if (filters.userId && post.userId !== Number(filters.userId)) continue;
155
+ if (filters.tag && !post.tags.includes(filters.tag.toLowerCase())) continue;
156
+ if (filters.q) {
157
+ const q = filters.q.toLowerCase();
158
+ if (!post.title.toLowerCase().includes(q) && !post.body.toLowerCase().includes(q)) continue;
159
+ }
160
+
161
+ result.push(post);
162
+ if (result.length >= targetCount) break;
163
+ }
164
+
165
+ return result;
166
+ }
167
+
168
+ function getPostById(id) {
169
+ const numericId = Number(id);
170
+ if (!numericId || numericId <= 0) return null;
171
+ if (numericId <= basePosts.length) {
172
+ return basePosts.find(p => p.id === numericId) || null;
173
+ }
174
+ return generatePost(numericId);
175
+ }
176
+
177
+ function getComments(optionsOrCount) {
178
+ let count = 5;
179
+ let filters = {};
180
+
181
+ if (typeof optionsOrCount === "number") {
182
+ count = optionsOrCount <= 0 ? 0 : optionsOrCount;
183
+ } else if (typeof optionsOrCount === "object" && optionsOrCount !== null) {
184
+ if (typeof optionsOrCount.count === "number") count = optionsOrCount.count;
185
+ else if (typeof optionsOrCount.limit === "number") count = optionsOrCount.limit;
186
+ filters = optionsOrCount;
187
+ }
188
+
189
+ const result = [];
190
+ const targetCount = count > 0 ? count : 0;
191
+ const poolSize = Math.max(targetCount, baseComments.length);
192
+
193
+ for (let i = 0; i < poolSize; i++) {
194
+ const comment = i < baseComments.length ? baseComments[i] : generateComment(i + 1);
195
+ if (filters.postId && comment.postId !== Number(filters.postId)) continue;
196
+ result.push(comment);
197
+ if (result.length >= targetCount) break;
198
+ }
199
+
200
+ return result;
201
+ }
202
+
203
+ function getCommentsByPostId(postId) {
204
+ return getComments({ postId: Number(postId), count: 10 });
205
+ }
206
+
207
+ module.exports = {
208
+ getPosts,
209
+ getPostById,
210
+ getComments,
211
+ getCommentsByPostId,
212
+ basePosts,
213
+ baseComments
214
+ };
@@ -0,0 +1,260 @@
1
+ const baseProducts = [
2
+ {
3
+ id: 1,
4
+ title: "Pro Wireless Noise-Cancelling Headphones",
5
+ description: "Premium over-ear wireless headphones with active noise cancellation, 40-hour battery life, and spatial audio support.",
6
+ price: 299.99,
7
+ discountPercentage: 12.5,
8
+ rating: 4.8,
9
+ stock: 45,
10
+ brand: "AuraSound",
11
+ category: "electronics",
12
+ thumbnail: "https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=500&auto=format&fit=crop&q=80",
13
+ images: [
14
+ "https://images.unsplash.com/photo-1505740420928-5e560c06d30e?w=500&auto=format&fit=crop&q=80",
15
+ "https://images.unsplash.com/photo-1484704849700-f032a568e944?w=500&auto=format&fit=crop&q=80"
16
+ ],
17
+ isAvailable: true
18
+ },
19
+ {
20
+ id: 2,
21
+ title: "UltraSlim Flagship Smartphone 256GB",
22
+ description: "6.7-inch Super AMOLED 120Hz display, quad-camera system with 108MP main sensor, and all-day fast-charge battery.",
23
+ price: 899.00,
24
+ discountPercentage: 8.0,
25
+ rating: 4.7,
26
+ stock: 28,
27
+ brand: "Vortex",
28
+ category: "smartphones",
29
+ thumbnail: "https://images.unsplash.com/photo-1511707171634-5f897ff02aa9?w=500&auto=format&fit=crop&q=80",
30
+ images: [
31
+ "https://images.unsplash.com/photo-1511707171634-5f897ff02aa9?w=500&auto=format&fit=crop&q=80"
32
+ ],
33
+ isAvailable: true
34
+ },
35
+ {
36
+ id: 3,
37
+ title: "Minimalist Mechanical Keyboard RGB",
38
+ description: "Compact 75% hot-swappable mechanical keyboard with lubricated linear switches, aluminum frame, and customizable PBT keycaps.",
39
+ price: 139.50,
40
+ discountPercentage: 15.0,
41
+ rating: 4.9,
42
+ stock: 62,
43
+ brand: "KeyPulse",
44
+ category: "electronics",
45
+ thumbnail: "https://images.unsplash.com/photo-1587829741301-dc798b83add3?w=500&auto=format&fit=crop&q=80",
46
+ images: [
47
+ "https://images.unsplash.com/photo-1587829741301-dc798b83add3?w=500&auto=format&fit=crop&q=80"
48
+ ],
49
+ isAvailable: true
50
+ },
51
+ {
52
+ id: 4,
53
+ title: "TitanBook 16-inch M-Pro Laptop",
54
+ description: "High-performance creator laptop featuring 32GB unified RAM, 1TB NVMe SSD, and 12-core processing architecture.",
55
+ price: 1899.99,
56
+ discountPercentage: 5.0,
57
+ rating: 4.9,
58
+ stock: 14,
59
+ brand: "Titan",
60
+ category: "laptops",
61
+ thumbnail: "https://images.unsplash.com/photo-1517336714731-489689fd1ca8?w=500&auto=format&fit=crop&q=80",
62
+ images: [
63
+ "https://images.unsplash.com/photo-1517336714731-489689fd1ca8?w=500&auto=format&fit=crop&q=80"
64
+ ],
65
+ isAvailable: true
66
+ },
67
+ {
68
+ id: 5,
69
+ title: "Artisan Roasted Single-Origin Coffee Beans (1kg)",
70
+ description: "Specialty Ethiopian Yirgacheffe medium roast with tasting notes of jasmine, bergamot, and sweet peach.",
71
+ price: 34.00,
72
+ discountPercentage: 0.0,
73
+ rating: 4.6,
74
+ stock: 120,
75
+ brand: "RoastMasters",
76
+ category: "groceries",
77
+ thumbnail: "https://images.unsplash.com/photo-1559056199-641a0ac8b55e?w=500&auto=format&fit=crop&q=80",
78
+ images: [
79
+ "https://images.unsplash.com/photo-1559056199-641a0ac8b55e?w=500&auto=format&fit=crop&q=80"
80
+ ],
81
+ isAvailable: true
82
+ },
83
+ {
84
+ id: 6,
85
+ title: "Nordic Minimalist Ceramic Desk Lamp",
86
+ description: "Warm LED dimmable ambient lamp with matte ceramic base and brushed brass accents, touch control dimmer.",
87
+ price: 79.90,
88
+ discountPercentage: 10.0,
89
+ rating: 4.5,
90
+ stock: 35,
91
+ brand: "Lumina Home",
92
+ category: "home-decoration",
93
+ thumbnail: "https://images.unsplash.com/photo-1507473885765-e6ed057f782c?w=500&auto=format&fit=crop&q=80",
94
+ images: [
95
+ "https://images.unsplash.com/photo-1507473885765-e6ed057f782c?w=500&auto=format&fit=crop&q=80"
96
+ ],
97
+ isAvailable: true
98
+ },
99
+ {
100
+ id: 7,
101
+ title: "Classic Waterproof Chronograph Watch",
102
+ description: "Stainless steel case, sapphire crystal glass, Japanese quartz movement, 100m water resistance, and genuine leather strap.",
103
+ price: 249.00,
104
+ discountPercentage: 20.0,
105
+ rating: 4.7,
106
+ stock: 19,
107
+ brand: "Chronos",
108
+ category: "fashion",
109
+ thumbnail: "https://images.unsplash.com/photo-1524592094714-0f0654e20314?w=500&auto=format&fit=crop&q=80",
110
+ images: [
111
+ "https://images.unsplash.com/photo-1524592094714-0f0654e20314?w=500&auto=format&fit=crop&q=80"
112
+ ],
113
+ isAvailable: true
114
+ },
115
+ {
116
+ id: 8,
117
+ title: "Clean Code & System Design Handbook",
118
+ description: "The essential guide to writing scalable, maintainable, and high-performance software systems for modern engineers.",
119
+ price: 49.99,
120
+ discountPercentage: 15.0,
121
+ rating: 4.95,
122
+ stock: 80,
123
+ brand: "TechPress",
124
+ category: "books",
125
+ thumbnail: "https://images.unsplash.com/photo-1532012164546-f432f2e3edd4?w=500&auto=format&fit=crop&q=80",
126
+ images: [
127
+ "https://images.unsplash.com/photo-1532012164546-f432f2e3edd4?w=500&auto=format&fit=crop&q=80"
128
+ ],
129
+ isAvailable: true
130
+ },
131
+ {
132
+ id: 9,
133
+ title: "Botanical Hydrating Facial Serum 50ml",
134
+ description: "Hyaluronic acid and vitamin C enriched antioxidant serum for radiant skin revitalization and 24h deep hydration.",
135
+ price: 42.50,
136
+ discountPercentage: 5.0,
137
+ rating: 4.4,
138
+ stock: 55,
139
+ brand: "PureGlow",
140
+ category: "skincare",
141
+ thumbnail: "https://images.unsplash.com/photo-1608248597359-5489725f3c95?w=500&auto=format&fit=crop&q=80",
142
+ images: [
143
+ "https://images.unsplash.com/photo-1608248597359-5489725f3c95?w=500&auto=format&fit=crop&q=80"
144
+ ],
145
+ isAvailable: true
146
+ },
147
+ {
148
+ id: 10,
149
+ title: "Ergonomic Mesh Executive Chair",
150
+ description: "Adjustable 4D armrests, dynamic lumbar support, breathable mesh back, and smooth-rolling silent casters.",
151
+ price: 389.00,
152
+ discountPercentage: 18.0,
153
+ rating: 4.8,
154
+ stock: 22,
155
+ brand: "ErgoForm",
156
+ category: "home-decoration",
157
+ thumbnail: "https://images.unsplash.com/photo-1580481077197-28564117b43a?w=500&auto=format&fit=crop&q=80",
158
+ images: [
159
+ "https://images.unsplash.com/photo-1580481077197-28564117b43a?w=500&auto=format&fit=crop&q=80"
160
+ ],
161
+ isAvailable: true
162
+ }
163
+ ];
164
+
165
+ const categories = ["electronics", "smartphones", "laptops", "groceries", "home-decoration", "fashion", "books", "skincare"];
166
+ const brands = ["AuraSound", "Vortex", "KeyPulse", "Titan", "RoastMasters", "Lumina Home", "Chronos", "TechPress", "PureGlow", "ErgoForm"];
167
+
168
+ function generateProduct(id) {
169
+ const category = categories[id % categories.length];
170
+ const brand = brands[id % brands.length];
171
+ const price = Number((19.99 + (id * 27.5) % 450).toFixed(2));
172
+ const discount = Number(((id * 3) % 25).toFixed(1));
173
+ const rating = Number((3.8 + ((id * 7) % 12) / 10).toFixed(1));
174
+ const stock = 10 + (id * 17) % 150;
175
+
176
+ return {
177
+ id,
178
+ title: `${brand} Standard Edition Item #${id}`,
179
+ description: `High-quality ${category} item designed with durability and premium performance in mind. Product ID: ${id}.`,
180
+ price,
181
+ discountPercentage: discount,
182
+ rating: Math.min(5.0, rating),
183
+ stock,
184
+ brand,
185
+ category,
186
+ thumbnail: `https://images.unsplash.com/photo-${1510000000000 + id}?w=500&auto=format&fit=crop&q=80`,
187
+ images: [
188
+ `https://images.unsplash.com/photo-${1510000000000 + id}?w=500&auto=format&fit=crop&q=80`
189
+ ],
190
+ isAvailable: stock > 0
191
+ };
192
+ }
193
+
194
+ function getProducts(optionsOrCount) {
195
+ let count = 10;
196
+ let filters = {};
197
+
198
+ if (typeof optionsOrCount === "number") {
199
+ count = optionsOrCount <= 0 ? 0 : optionsOrCount;
200
+ } else if (typeof optionsOrCount === "object" && optionsOrCount !== null) {
201
+ if (typeof optionsOrCount.count === "number") {
202
+ count = optionsOrCount.count <= 0 ? 0 : optionsOrCount.count;
203
+ } else if (typeof optionsOrCount.limit === "number") {
204
+ count = optionsOrCount.limit <= 0 ? 0 : optionsOrCount.limit;
205
+ }
206
+ filters = optionsOrCount;
207
+ }
208
+
209
+ const result = [];
210
+ const targetCount = count > 0 ? count : 0;
211
+ const poolSize = Math.max(targetCount, baseProducts.length);
212
+
213
+ for (let i = 0; i < poolSize; i++) {
214
+ const product = i < baseProducts.length ? baseProducts[i] : generateProduct(i + 1);
215
+
216
+ if (filters.category && product.category.toLowerCase() !== filters.category.toLowerCase()) continue;
217
+ if (filters.brand && product.brand.toLowerCase() !== filters.brand.toLowerCase()) continue;
218
+ if (typeof filters.minPrice === "number" && product.price < filters.minPrice) continue;
219
+ if (typeof filters.maxPrice === "number" && product.price > filters.maxPrice) continue;
220
+ if (typeof filters.rating === "number" && product.rating < filters.rating) continue;
221
+ if (typeof filters.isAvailable === "boolean" && product.isAvailable !== filters.isAvailable) continue;
222
+ if (filters.q) {
223
+ const q = filters.q.toLowerCase();
224
+ const match = product.title.toLowerCase().includes(q) ||
225
+ product.description.toLowerCase().includes(q) ||
226
+ product.brand.toLowerCase().includes(q);
227
+ if (!match) continue;
228
+ }
229
+
230
+ result.push(product);
231
+ if (result.length >= targetCount) break;
232
+ }
233
+
234
+ if (filters.sortField) {
235
+ const field = filters.sortField;
236
+ const order = filters.sortOrder === "desc" ? -1 : 1;
237
+ result.sort((a, b) => {
238
+ if (a[field] < b[field]) return -1 * order;
239
+ if (a[field] > b[field]) return 1 * order;
240
+ return 0;
241
+ });
242
+ }
243
+
244
+ return result;
245
+ }
246
+
247
+ function getProductById(id) {
248
+ const numericId = Number(id);
249
+ if (!numericId || numericId <= 0) return null;
250
+ if (numericId <= baseProducts.length) {
251
+ return baseProducts.find(p => p.id === numericId) || null;
252
+ }
253
+ return generateProduct(numericId);
254
+ }
255
+
256
+ module.exports = {
257
+ getProducts,
258
+ getProductById,
259
+ baseProducts
260
+ };