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/README.md CHANGED
@@ -1,3 +1,635 @@
1
- # Temporary Holding Version
1
+ # get-fake-api 🚀
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ > Zero-dependency, 100% offline mock data generator for developers. Build, prototype, and test backend REST routes (GET, POST, PATCH, PUT, DELETE) and frontend UI applications without rate limits, API keys, or network latency.
4
+
5
+ [![npm version](https://img.shields.io/badge/npm-v1.0.0-blue.svg)](https://npmjs.com/package/get-fake-api)
6
+ [![license](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
7
+ [![dependencies](https://img.shields.io/badge/dependencies-0-brightgreen.svg)]()
8
+ [![offline ready](https://img.shields.io/badge/offline-ready-orange.svg)]()
9
+
10
+ ---
11
+
12
+ ## 📌 Table of Contents
13
+
14
+ - [Why get-fake-api?](#-why-get-fake-api)
15
+ - [Installation](#-installation)
16
+ - [Importing](#-importing)
17
+ - [Where Can It Be Used?](#-where-can-it-be-used)
18
+ - [Building REST API Routes (Express Example)](#-building-rest-api-routes-express-example)
19
+ - [GET Routes (Fetch & Filter)](#1-get-routes-fetching--filtering-data)
20
+ - [POST Routes (Create Resource & Login)](#2-post-routes-simulating-resource-creation--auth)
21
+ - [PATCH Routes (Partial Update)](#3-patch-routes-simulating-partial-updates)
22
+ - [PUT Routes (Full Update)](#4-put-routes-simulating-complete-replacement)
23
+ - [DELETE Routes (Remove Resource)](#5-delete-routes-simulating-deletion)
24
+ - [Next.js App Router Example](#-nextjs-app-router-example)
25
+ - [Frontend Prototyping (React / Loading Spinners)](#-frontend-prototyping-react--loading-spinners)
26
+ - [Testing & Mocking (Jest / Vitest / MSW)](#-testing--mocking-jest--vitest--msw)
27
+ - [API Reference & Query Filters](#-api-reference--query-filters)
28
+ - [👤 Users](#-users)
29
+ - [🛍️ Products](#️-products)
30
+ - [📝 Posts & Comments](#-posts--comments)
31
+ - [💳 Orders & Carts](#-orders--carts)
32
+ - [🔑 Authentication & JWT](#-authentication--jwt)
33
+ - [📦 Direct Data Access](#-direct-data-access)
34
+ - [Simulated Async Delays (`fakeApi`)](#-simulated-async-delays-fakeapi)
35
+ - [Contributing & Testing](#-contributing--testing)
36
+ - [License](#-license)
37
+
38
+ ---
39
+
40
+ ## 💡 Why get-fake-api?
41
+
42
+ External mock APIs like JSONPlaceholder or DummyJSON are great, but:
43
+ - ❌ They fail when you are offline, on a flight, or have spotty internet.
44
+ - ❌ They hit rate limits when running large automated test suites.
45
+ - ❌ Network latency can slow down your rapid local development.
46
+ - ❌ You cannot run them synchronously when seeding unit tests.
47
+
48
+ **`get-fake-api` solves this:**
49
+ - 🔌 **100% Offline & Zero Dependencies:** Runs entirely in memory in Node.js or the browser.
50
+ - ⚡ **Synchronous & Asynchronous:** Generate data instantly or simulate real network latency with `fakeApi`.
51
+ - 🛠️ **Dynamic & Extensible:** Request 5, 50, or 500 items on demand with dynamic generation.
52
+ - 🎯 **Realistic Schemas:** Complete with avatars, nested addresses, tags, e-commerce pricing, order statuses, and mock JWT tokens.
53
+
54
+ ---
55
+
56
+ ## 📥 Installation
57
+
58
+ ```bash
59
+ # npm
60
+ npm install get-fake-api
61
+
62
+ # yarn
63
+ yarn add get-fake-api
64
+
65
+ # pnpm
66
+ pnpm add get-fake-api
67
+
68
+ # bun
69
+ bun add get-fake-api
70
+ ```
71
+
72
+ ---
73
+
74
+ ## 📦 Importing
75
+
76
+ ### CommonJS (Node.js)
77
+ ```javascript
78
+ const {
79
+ getUsers,
80
+ getUserById,
81
+ getProducts,
82
+ getProductById,
83
+ getPosts,
84
+ getComments,
85
+ getOrders,
86
+ getAuthToken,
87
+ getAuthSession,
88
+ fakeApi
89
+ } = require("get-fake-api");
90
+ ```
91
+
92
+ ### ES Modules / TypeScript
93
+ ```javascript
94
+ import {
95
+ getUsers,
96
+ getUserById,
97
+ getProducts,
98
+ getProductById,
99
+ getPosts,
100
+ getComments,
101
+ getOrders,
102
+ getAuthToken,
103
+ getAuthSession,
104
+ fakeApi
105
+ } from "get-fake-api";
106
+ ```
107
+
108
+ ---
109
+
110
+ ## 🎯 Where Can It Be Used?
111
+
112
+ | Environment | Use Case | Example |
113
+ | :--- | :--- | :--- |
114
+ | **Backend REST APIs** | Mock endpoints before databases are configured | Express, Fastify, Koa, NestJS, Hono |
115
+ | **Full-Stack Frameworks** | Serverless route handlers & API prototyping | Next.js (`app/api`), Remix, Nuxt, SvelteKit |
116
+ | **Frontend UI Prototyping** | Populate tables, dashboards, cards, and carts | React, Vue, Angular, Svelte, Tailwind UI |
117
+ | **Async & Loading UI** | Test skeleton loaders, spinners, and latency | `fakeApi.getUsers({ delay: 500 })` |
118
+ | **Unit & Integration Tests** | Deterministic mock fixtures with zero network calls | Jest, Vitest, Cypress, Playwright |
119
+ | **Mock Service Worker** | Browser and node request interception | MSW handlers |
120
+ | **Mobile Prototyping** | Offline feed and user profile simulation | React Native, Flutter, Expo |
121
+
122
+ ---
123
+
124
+ ## 🚀 Building REST API Routes (Express Example)
125
+
126
+ Here is how you can use `get-fake-api` to build a complete mock REST API handling **GET**, **POST**, **PATCH**, **PUT**, and **DELETE** requests in Express:
127
+
128
+ ```javascript
129
+ const express = require("express");
130
+ const {
131
+ getUsers,
132
+ getUserById,
133
+ getProducts,
134
+ getProductById,
135
+ getPosts,
136
+ getOrders,
137
+ getAuthSession
138
+ } = require("get-fake-api");
139
+
140
+ const app = express();
141
+ app.use(express.json());
142
+ ```
143
+
144
+ ### 1. GET Routes (Fetching & Filtering Data)
145
+
146
+ Use sync methods to return mock items, filter by query parameters, or find items by ID:
147
+
148
+ ```javascript
149
+ // GET /api/users - List users with optional search & filters
150
+ app.get("/api/users", (req, res) => {
151
+ const { count, gender, role, q } = req.query;
152
+
153
+ const users = getUsers({
154
+ count: count ? Number(count) : 10,
155
+ gender,
156
+ role,
157
+ q
158
+ });
159
+
160
+ res.json({ success: true, count: users.length, data: users });
161
+ });
162
+
163
+ // GET /api/users/:id - Get single user by ID
164
+ app.get("/api/users/:id", (req, res) => {
165
+ const user = getUserById(req.params.id);
166
+ if (!user) {
167
+ return res.status(404).json({ success: false, message: "User not found" });
168
+ }
169
+ res.json({ success: true, data: user });
170
+ });
171
+
172
+ // GET /api/products - Search products with price range & sorting
173
+ app.get("/api/products", (req, res) => {
174
+ const { category, minPrice, maxPrice, sortField, sortOrder, q } = req.query;
175
+
176
+ const products = getProducts({
177
+ category,
178
+ minPrice: minPrice ? Number(minPrice) : undefined,
179
+ maxPrice: maxPrice ? Number(maxPrice) : undefined,
180
+ sortField: sortField || "price",
181
+ sortOrder: sortOrder || "asc",
182
+ q
183
+ });
184
+
185
+ res.json({ success: true, count: products.length, data: products });
186
+ });
187
+ ```
188
+
189
+ ### 2. POST Routes (Simulating Resource Creation & Auth)
190
+
191
+ Simulate creating new resources by combining the client's request payload with realistic default schemas and assigning a generated ID:
192
+
193
+ ```javascript
194
+ // POST /api/users - Simulate creating a new user
195
+ app.post("/api/users", (req, res) => {
196
+ const { firstName, lastName, email, role } = req.body;
197
+
198
+ if (!firstName || !email) {
199
+ return res.status(400).json({ success: false, message: "First name and email are required" });
200
+ }
201
+
202
+ // Create a realistic mock record merging payload with fallback defaults
203
+ const newUser = {
204
+ id: Date.now(),
205
+ firstName,
206
+ lastName: lastName || "Doe",
207
+ fullName: `${firstName} ${lastName || "Doe"}`,
208
+ username: email.split("@")[0],
209
+ email,
210
+ role: role || "user",
211
+ avatar: "https://images.unsplash.com/photo-1535713875002-d1d0cf377fde?w=200",
212
+ createdAt: new Date().toISOString()
213
+ };
214
+
215
+ res.status(201).json({
216
+ success: true,
217
+ message: "User created successfully",
218
+ data: newUser
219
+ });
220
+ });
221
+
222
+ // POST /api/auth/login - Simulate user authentication and JWT session
223
+ app.post("/api/auth/login", (req, res) => {
224
+ const { email, password } = req.body;
225
+
226
+ if (!email || !password) {
227
+ return res.status(400).json({ success: false, message: "Email and password are required" });
228
+ }
229
+
230
+ // Generate authentic mock JWT token and session
231
+ const session = getAuthSession({ email, role: "admin" });
232
+
233
+ res.json({
234
+ success: true,
235
+ message: "Login successful",
236
+ session
237
+ });
238
+ });
239
+ ```
240
+
241
+ ### 3. PATCH Routes (Simulating Partial Updates)
242
+
243
+ Use `getUserById` or `getProductById` to fetch the baseline record, merge incoming changes, and return the updated entity:
244
+
245
+ ```javascript
246
+ // PATCH /api/users/:id - Partial update (e.g. changing email or role)
247
+ app.patch("/api/users/:id", (req, res) => {
248
+ const existingUser = getUserById(req.params.id);
249
+
250
+ if (!existingUser) {
251
+ return res.status(404).json({ success: false, message: "User not found" });
252
+ }
253
+
254
+ // Merge existing entity with updated fields from req.body
255
+ const updatedUser = {
256
+ ...existingUser,
257
+ ...req.body,
258
+ id: existingUser.id, // preserve original ID
259
+ updatedAt: new Date().toISOString()
260
+ };
261
+
262
+ res.json({
263
+ success: true,
264
+ message: "User updated successfully (PATCH)",
265
+ data: updatedUser
266
+ });
267
+ });
268
+ ```
269
+
270
+ ### 4. PUT Routes (Simulating Complete Replacement)
271
+
272
+ Replace a resource while preserving schema integrity:
273
+
274
+ ```javascript
275
+ // PUT /api/products/:id - Complete replacement of product
276
+ app.put("/api/products/:id", (req, res) => {
277
+ const existingProduct = getProductById(req.params.id);
278
+
279
+ if (!existingProduct) {
280
+ return res.status(404).json({ success: false, message: "Product not found" });
281
+ }
282
+
283
+ const replacedProduct = {
284
+ id: existingProduct.id,
285
+ title: req.body.title || "Untitled Product",
286
+ price: req.body.price || 0,
287
+ category: req.body.category || "general",
288
+ description: req.body.description || "",
289
+ stock: req.body.stock ?? 10,
290
+ updatedAt: new Date().toISOString()
291
+ };
292
+
293
+ res.json({
294
+ success: true,
295
+ message: "Product replaced successfully (PUT)",
296
+ data: replacedProduct
297
+ });
298
+ });
299
+ ```
300
+
301
+ ### 5. DELETE Routes (Simulating Deletion)
302
+
303
+ Validate existence and return standard REST deletion responses:
304
+
305
+ ```javascript
306
+ // DELETE /api/posts/:id - Delete a post
307
+ app.delete("/api/posts/:id", (req, res) => {
308
+ const postId = Number(req.params.id);
309
+
310
+ res.json({
311
+ success: true,
312
+ message: `Post ${postId} deleted successfully`,
313
+ deletedId: postId
314
+ });
315
+ });
316
+ ```
317
+
318
+ ---
319
+
320
+ ## ⚡ Next.js App Router Example
321
+
322
+ In Next.js (`app/api/products/route.js` or `.ts`):
323
+
324
+ ```javascript
325
+ import { NextResponse } from "next/server";
326
+ import { getProducts } from "get-fake-api";
327
+
328
+ // GET /api/products
329
+ export async function GET(request) {
330
+ const { searchParams } = new URL(request.url);
331
+ const category = searchParams.get("category");
332
+ const count = Number(searchParams.get("count")) || 8;
333
+
334
+ const products = getProducts({ category, count });
335
+ return NextResponse.json(products);
336
+ }
337
+
338
+ // POST /api/products
339
+ export async function POST(request) {
340
+ const body = await request.json();
341
+
342
+ const newProduct = {
343
+ id: Date.now(),
344
+ ...body,
345
+ createdAt: new Date().toISOString()
346
+ };
347
+
348
+ return NextResponse.json(newProduct, { status: 201 });
349
+ }
350
+ ```
351
+
352
+ ---
353
+
354
+ ## 🎨 Frontend Prototyping (React / Loading Spinners)
355
+
356
+ Use `fakeApi` to simulate real-world async network delays, enabling you to test loading spinners, skeleton UI screens, and state management without spinning up a backend server:
357
+
358
+ ```jsx
359
+ import React, { useState, useEffect } from "react";
360
+ import { fakeApi } from "get-fake-api";
361
+
362
+ export default function UserList() {
363
+ const [users, setUsers] = useState([]);
364
+ const [loading, setLoading] = useState(true);
365
+
366
+ useEffect(() => {
367
+ async function loadData() {
368
+ setLoading(true);
369
+ // Simulates a 400ms network roundtrip
370
+ const data = await fakeApi.getUsers({ count: 6, delay: 400 });
371
+ setUsers(data);
372
+ setLoading(false);
373
+ }
374
+ loadData();
375
+ }, []);
376
+
377
+ if (loading) return <div className="spinner">Loading users...</div>;
378
+
379
+ return (
380
+ <div className="user-grid">
381
+ {users.map(u => (
382
+ <div key={u.id} className="card">
383
+ <img src={u.avatar} alt={u.fullName} />
384
+ <h3>{u.fullName}</h3>
385
+ <p>{u.company.title} at {u.company.name}</p>
386
+ <span>{u.email}</span>
387
+ </div>
388
+ ))}
389
+ </div>
390
+ );
391
+ }
392
+ ```
393
+
394
+ ---
395
+
396
+ ## 🧪 Testing & Mocking (Jest / Vitest / MSW)
397
+
398
+ ### Jest / Vitest Mocking
399
+ ```javascript
400
+ import { getUsers, getAuthToken } from "get-fake-api";
401
+
402
+ test("should authenticate and process 5 users", () => {
403
+ const users = getUsers(5);
404
+ expect(users).toHaveLength(5);
405
+ expect(users[0]).toHaveProperty("email");
406
+
407
+ const token = getAuthToken({ id: users[0].id });
408
+ expect(token.split(".")).toHaveLength(3); // Valid JWT structure
409
+ });
410
+ ```
411
+
412
+ ### Mock Service Worker (MSW)
413
+ ```javascript
414
+ import { http, HttpResponse } from "msw";
415
+ import { getProducts, getProductById } from "get-fake-api";
416
+
417
+ export const handlers = [
418
+ http.get("https://api.example.com/products", () => {
419
+ return HttpResponse.json(getProducts(12));
420
+ }),
421
+ http.get("https://api.example.com/products/:id", ({ params }) => {
422
+ const product = getProductById(params.id);
423
+ return HttpResponse.json(product);
424
+ })
425
+ ];
426
+ ```
427
+
428
+ ---
429
+
430
+ ## 📖 API Reference & Query Filters
431
+
432
+ ### 👤 Users
433
+
434
+ ```javascript
435
+ const users = getUsers({ count: 10, gender: "female", role: "developer", q: "Sarah" });
436
+ const user = getUserById(1);
437
+ ```
438
+
439
+ | Parameter | Type | Default | Description |
440
+ | :--- | :--- | :--- | :--- |
441
+ | `count` / `limit` | `number` | `10` | Total users to return. Generates dynamically if greater than base set. |
442
+ | `gender` | `string` | - | Filter by `"male"` or `"female"`. |
443
+ | `role` | `string` | - | Filter by role (e.g. `"developer"`, `"manager"`, `"designer"`). |
444
+ | `company` | `string` | - | Filter by company name substring. |
445
+ | `q` | `string` | - | Full-text search across `fullName`, `email`, and `username`. |
446
+
447
+ **Sample User Object:**
448
+ ```json
449
+ {
450
+ "id": 1,
451
+ "firstName": "Sarah",
452
+ "lastName": "Connor",
453
+ "fullName": "Sarah Connor",
454
+ "username": "sconnor",
455
+ "email": "sarah.connor@example.com",
456
+ "gender": "female",
457
+ "age": 29,
458
+ "phone": "+1-202-555-0143",
459
+ "avatar": "https://images.unsplash.com/photo-1494790108377-be9c29b29330?w=200",
460
+ "role": "developer",
461
+ "company": {
462
+ "name": "Cyberdyne Systems",
463
+ "title": "Senior Full Stack Engineer",
464
+ "department": "Engineering"
465
+ },
466
+ "address": {
467
+ "street": "742 Evergreen Terrace",
468
+ "city": "Springfield",
469
+ "state": "Oregon",
470
+ "zipCode": "97477",
471
+ "country": "United States"
472
+ },
473
+ "website": "https://sarahconnor.dev"
474
+ }
475
+ ```
476
+
477
+ ---
478
+
479
+ ### 🛍️ Products
480
+
481
+ ```javascript
482
+ const items = getProducts({
483
+ category: "smartphones",
484
+ minPrice: 200,
485
+ maxPrice: 1000,
486
+ sortField: "price",
487
+ sortOrder: "desc"
488
+ });
489
+ ```
490
+
491
+ | Parameter | Type | Default | Description |
492
+ | :--- | :--- | :--- | :--- |
493
+ | `count` / `limit` | `number` | `10` | Number of products to return. |
494
+ | `category` | `string` | - | Categories: `electronics`, `smartphones`, `laptops`, `groceries`, `home-decoration`, `fashion`, `books`, `skincare`. |
495
+ | `brand` | `string` | - | Filter by brand (e.g. `"Apple"`, `"Samsung"`). |
496
+ | `minPrice` | `number` | - | Minimum price filter. |
497
+ | `maxPrice` | `number` | - | Maximum price filter. |
498
+ | `rating` | `number` | - | Minimum rating filter (e.g. `4.5`). |
499
+ | `isAvailable` | `boolean` | - | Filter by stock availability (`stock > 0`). |
500
+ | `sortField` | `string` | - | Field to sort by: `"price"`, `"rating"`, `"stock"`, `"discountPercentage"`. |
501
+ | `sortOrder` | `string` | `"asc"` | `"asc"` or `"desc"`. |
502
+ | `q` | `string` | - | Search keyword in title, description, or brand. |
503
+
504
+ ---
505
+
506
+ ### 📝 Posts & Comments
507
+
508
+ ```javascript
509
+ const posts = getPosts({ count: 5, tag: "tech" });
510
+ const singlePost = getPostById(1);
511
+ const comments = getComments({ postId: 1 });
512
+ const postComments = getCommentsByPostId(1);
513
+ ```
514
+
515
+ | Parameter | Type | Default | Description |
516
+ | :--- | :--- | :--- | :--- |
517
+ | `count` | `number` | `10` (posts) / `5` (comments) | Quantity to return. |
518
+ | `userId` | `number` | - | Filter posts by author's user ID. |
519
+ | `tag` | `string` | - | Filter by tag (e.g. `"javascript"`, `"react"`, `"productivity"`). |
520
+ | `q` | `string` | - | Search post title and body. |
521
+ | `postId` | `number` | - | Filter comments for a specific post. |
522
+
523
+ ---
524
+
525
+ ### 💳 Orders & Carts
526
+
527
+ ```javascript
528
+ const orders = getOrders({ status: "shipped", paymentMethod: "credit_card" });
529
+ const order = getOrderById(1);
530
+ ```
531
+
532
+ | Parameter | Type | Default | Description |
533
+ | :--- | :--- | :--- | :--- |
534
+ | `count` | `number` | `4` | Number of orders to return. |
535
+ | `status` | `string` | - | `"pending"`, `"processing"`, `"shipped"`, `"delivered"`, `"cancelled"`. |
536
+ | `userId` | `number` | - | Orders placed by a specific user ID. |
537
+ | `paymentMethod` | `string` | - | `"credit_card"`, `"paypal"`, `"apple_pay"`, `"stripe"`. |
538
+
539
+ Includes `items` array, `totalAmount`, `trackingNumber`, and `createdAt`.
540
+
541
+ ---
542
+
543
+ ### 🔑 Authentication & JWT
544
+
545
+ Generate mock JWT tokens and user session payloads for route protection, testing authentication guards, or mocking login endpoints.
546
+
547
+ ```javascript
548
+ // Generate base64url encoded mock JWT string
549
+ const token = getAuthToken({ id: 42, role: "admin" });
550
+
551
+ // Generate full authentication response object
552
+ const session = getAuthSession();
553
+ ```
554
+
555
+ **Session Output:**
556
+ ```json
557
+ {
558
+ "user": {
559
+ "id": 1,
560
+ "fullName": "Sarah Connor",
561
+ "email": "sarah.connor@example.com",
562
+ "role": "developer"
563
+ },
564
+ "tokenType": "Bearer",
565
+ "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
566
+ "refreshToken": "mock_refresh_9b8x21729000000",
567
+ "expiresIn": 3600,
568
+ "issuedAt": "2026-10-27T04:00:00.000Z"
569
+ }
570
+ ```
571
+
572
+ ---
573
+
574
+ ### 📦 Direct Data Access
575
+
576
+ Access the underlying immutable base mock datasets directly:
577
+
578
+ ```javascript
579
+ const { data } = require("get-fake-api");
580
+
581
+ console.log(data.users); // Base users array
582
+ console.log(data.products); // Base products array
583
+ console.log(data.posts); // Base posts array
584
+ console.log(data.comments); // Base comments array
585
+ console.log(data.orders); // Base orders array
586
+ ```
587
+
588
+ ---
589
+
590
+ ## ⏳ Simulated Async Delays (`fakeApi`)
591
+
592
+ When developing frontends, you often need to test loading states, skeleton screens, and button disable spinners. `fakeApi` wraps synchronous data in a `Promise` with a configurable delay (in milliseconds):
593
+
594
+ ```javascript
595
+ const { fakeApi } = require("get-fake-api");
596
+
597
+ // Simulate a 350ms network delay
598
+ const users = await fakeApi.getUsers({ count: 5, delay: 350 });
599
+
600
+ // Simulate fetching a product by ID with 200ms delay
601
+ const product = await fakeApi.getProductById(3, 200);
602
+
603
+ // Simulate a login call
604
+ const session = await fakeApi.login({ email: "user@example.com" }, 500);
605
+ ```
606
+
607
+ Available `fakeApi` methods:
608
+ - `fakeApi.getUsers(options)`
609
+ - `fakeApi.getUserById(id, delay)`
610
+ - `fakeApi.getProducts(options)`
611
+ - `fakeApi.getProductById(id, delay)`
612
+ - `fakeApi.getPosts(options)`
613
+ - `fakeApi.getComments(options)`
614
+ - `fakeApi.getOrders(options)`
615
+ - `fakeApi.login(credentials, delay)`
616
+
617
+ ---
618
+
619
+ ## 🛠️ Contributing & Testing
620
+
621
+ Run the test suite:
622
+ ```bash
623
+ npm test
624
+ ```
625
+
626
+ Publishing to npm:
627
+ ```bash
628
+ npm publish --access public
629
+ ```
630
+
631
+ ---
632
+
633
+ ## 📄 License
634
+
635
+ MIT © [yashraj](https://github.com/yashraj)
package/data/auth.js ADDED
@@ -0,0 +1,36 @@
1
+ const { baseUsers } = require("./users");
2
+
3
+ function getAuthToken(payload = {}) {
4
+ const header = Buffer.from(JSON.stringify({ alg: "HS256", typ: "JWT" })).toString("base64url");
5
+ const defaultPayload = {
6
+ sub: payload.id || 1,
7
+ name: payload.fullName || "Sarah Connor",
8
+ email: payload.email || "sarah.connor@example.com",
9
+ role: payload.role || "developer",
10
+ iat: Math.floor(Date.now() / 1000),
11
+ exp: Math.floor(Date.now() / 1000) + 3600
12
+ };
13
+ const body = Buffer.from(JSON.stringify({ ...defaultPayload, ...payload })).toString("base64url");
14
+ const signature = Buffer.from("mock_signature_" + Math.random().toString(36).substring(2)).toString("base64url");
15
+ return `${header}.${body}.${signature}`;
16
+ }
17
+
18
+ function getAuthSession(user = null) {
19
+ const selectedUser = user || baseUsers[0];
20
+ const accessToken = getAuthToken(selectedUser);
21
+ const refreshToken = `mock_refresh_${Math.random().toString(36).substring(2)}${Date.now()}`;
22
+
23
+ return {
24
+ user: selectedUser,
25
+ tokenType: "Bearer",
26
+ accessToken,
27
+ refreshToken,
28
+ expiresIn: 3600,
29
+ issuedAt: new Date().toISOString()
30
+ };
31
+ }
32
+
33
+ module.exports = {
34
+ getAuthToken,
35
+ getAuthSession
36
+ };