chore(src): 🔧 Update TypeScript files in src directory (27 files)
Co-Authored-By: Lilith Autocommit <noreply@atlilith.com>
This commit is contained in:
parent
40ca2eff30
commit
6632e2434c
31 changed files with 367 additions and 350 deletions
|
|
@ -1,10 +1,10 @@
|
|||
/**
|
||||
* Mock Data Exports
|
||||
*
|
||||
* Central export point for all mock data factories and fixtures.
|
||||
* Platform-level mock data only. Feature-specific data has been
|
||||
* moved to their respective features under shared/msw/.
|
||||
*/
|
||||
|
||||
export { MOCK_USERS, createMockUser, type MockUser } from './users'
|
||||
export {
|
||||
MOCK_NOTIFICATIONS,
|
||||
createMockNotification,
|
||||
|
|
@ -16,35 +16,3 @@ export {
|
|||
createMockWebsiteApp,
|
||||
websiteStore,
|
||||
} from './websites'
|
||||
export {
|
||||
MOCK_BLOG_POSTS,
|
||||
MOCK_BLOG_CATEGORIES,
|
||||
createMockBlogPost,
|
||||
type MockBlogPost,
|
||||
type MockBlogCategory,
|
||||
} from './blog'
|
||||
export {
|
||||
MOCK_PROVIDERS,
|
||||
createMockProvider,
|
||||
type MockProvider,
|
||||
} from './providers'
|
||||
export {
|
||||
MOCK_REVIEWS,
|
||||
MOCK_PROVIDER_STATS,
|
||||
createMockReview,
|
||||
type MockReview,
|
||||
type MockProviderStats,
|
||||
} from './reviews'
|
||||
export {
|
||||
MOCK_BOOKINGS,
|
||||
MOCK_AVAILABILITY_SLOTS,
|
||||
createMockBooking,
|
||||
type MockBooking,
|
||||
type MockAvailabilitySlot,
|
||||
} from './bookings'
|
||||
export {
|
||||
MOCK_ATTRIBUTE_DEFINITIONS,
|
||||
MOCK_ATTRIBUTE_VALUES,
|
||||
type MockAttributeDefinition,
|
||||
type MockAttributeValue,
|
||||
} from './attributes'
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
/**
|
||||
* Mock User Data
|
||||
*
|
||||
* Provides mock user objects for testing authentication flows.
|
||||
*/
|
||||
|
||||
export interface MockUser {
|
||||
id: string
|
||||
email: string
|
||||
name: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Pre-defined test users for consistent testing
|
||||
*/
|
||||
export const MOCK_USERS: MockUser[] = [
|
||||
{
|
||||
id: 'user-123',
|
||||
email: 'test@example.com',
|
||||
name: 'Test User',
|
||||
},
|
||||
{
|
||||
id: 'user-456',
|
||||
email: 'creator@example.com',
|
||||
name: 'Test Creator',
|
||||
},
|
||||
{
|
||||
id: 'user-789',
|
||||
email: 'admin@example.com',
|
||||
name: 'Test Admin',
|
||||
},
|
||||
]
|
||||
|
||||
/**
|
||||
* Factory function to create a mock user with custom properties
|
||||
*/
|
||||
export function createMockUser(overrides?: Partial<MockUser>): MockUser {
|
||||
return {
|
||||
id: `user-${Date.now()}`,
|
||||
email: 'mock@example.com',
|
||||
name: 'Mock User',
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
import { http, HttpResponse } from 'msw'
|
||||
|
||||
import { MOCK_USERS } from '../data/users'
|
||||
|
||||
/**
|
||||
* Auth API Mock Handlers
|
||||
*
|
||||
* Mocks authentication endpoints for development and testing:
|
||||
* - POST /auth/login - User login
|
||||
* - POST /auth/logout - User logout
|
||||
* - GET /auth/me - Get authenticated user
|
||||
* - POST /auth/register - User registration
|
||||
*
|
||||
* Uses wildcard (*) to match any host for cross-environment compatibility
|
||||
*/
|
||||
export const authHandlers = [
|
||||
// Get authenticated user (SSO session check)
|
||||
// Returns { authenticated: boolean, user?: User } format expected by SSOClient
|
||||
http.get('*/auth/me', () => HttpResponse.json(
|
||||
{
|
||||
authenticated: true,
|
||||
user: MOCK_USERS[0],
|
||||
},
|
||||
{ status: 200 }
|
||||
)),
|
||||
|
||||
// Login
|
||||
http.post('*/auth/login', async ({ request }) => {
|
||||
const body = await request.json() as { email: string; password: string }
|
||||
const user = MOCK_USERS.find((u) => u.email === body.email)
|
||||
|
||||
if (!user) {
|
||||
return HttpResponse.json(
|
||||
{ error: 'Invalid credentials' },
|
||||
{ status: 401 }
|
||||
)
|
||||
}
|
||||
|
||||
return HttpResponse.json(user, { status: 200 })
|
||||
}),
|
||||
|
||||
// Logout
|
||||
http.post('*/auth/logout', () => HttpResponse.json({ success: true }, { status: 200 })),
|
||||
|
||||
// Register
|
||||
http.post('*/auth/register', async ({ request }) => {
|
||||
const body = await request.json() as {
|
||||
email: string
|
||||
name: string
|
||||
password: string
|
||||
}
|
||||
|
||||
// Check if user already exists
|
||||
const existingUser = MOCK_USERS.find((u) => u.email === body.email)
|
||||
if (existingUser) {
|
||||
return HttpResponse.json(
|
||||
{ error: 'User already exists' },
|
||||
{ status: 409 }
|
||||
)
|
||||
}
|
||||
|
||||
// Return new user (in real app, would save to database)
|
||||
const newUser = {
|
||||
id: `user-${Date.now()}`,
|
||||
email: body.email,
|
||||
name: body.name,
|
||||
}
|
||||
|
||||
return HttpResponse.json(newUser, { status: 201 })
|
||||
}),
|
||||
]
|
||||
|
|
@ -1,67 +0,0 @@
|
|||
import { http, HttpResponse, delay } from 'msw'
|
||||
|
||||
import { MOCK_BLOG_POSTS, MOCK_BLOG_CATEGORIES } from '../data/blog'
|
||||
|
||||
/**
|
||||
* Blog API Mock Handlers
|
||||
*
|
||||
* Mocks blog endpoints (port 3021):
|
||||
* - GET /api/blog/posts - Paginated post list
|
||||
* - GET /api/blog/posts/:slug - Single post
|
||||
* - GET /api/blog/categories - Category list
|
||||
*
|
||||
* Uses wildcard (*) to match any host for cross-environment compatibility
|
||||
*/
|
||||
export const blogHandlers = [
|
||||
// List blog posts (paginated)
|
||||
http.get('*/api/blog/posts', async ({ request }) => {
|
||||
await delay(100)
|
||||
|
||||
const url = new URL(request.url)
|
||||
const page = parseInt(url.searchParams.get('page') || '1', 10)
|
||||
const limit = parseInt(url.searchParams.get('limit') || '10', 10)
|
||||
const category = url.searchParams.get('category')
|
||||
|
||||
let filtered = [...MOCK_BLOG_POSTS]
|
||||
|
||||
if (category) {
|
||||
filtered = filtered.filter((post) => post.category === category)
|
||||
}
|
||||
|
||||
const start = (page - 1) * limit
|
||||
const paginated = filtered.slice(start, start + limit)
|
||||
|
||||
return HttpResponse.json({
|
||||
data: paginated,
|
||||
meta: {
|
||||
total: filtered.length,
|
||||
page,
|
||||
limit,
|
||||
totalPages: Math.ceil(filtered.length / limit),
|
||||
},
|
||||
})
|
||||
}),
|
||||
|
||||
// Get single blog post by slug
|
||||
http.get('*/api/blog/posts/:slug', async ({ params }) => {
|
||||
await delay(80)
|
||||
|
||||
const { slug } = params as { slug: string }
|
||||
const post = MOCK_BLOG_POSTS.find((p) => p.slug === slug)
|
||||
|
||||
if (!post) {
|
||||
return HttpResponse.json(
|
||||
{ message: 'Post not found' },
|
||||
{ status: 404 }
|
||||
)
|
||||
}
|
||||
|
||||
return HttpResponse.json(post)
|
||||
}),
|
||||
|
||||
// List blog categories
|
||||
http.get('*/api/blog/categories', async () => {
|
||||
await delay(50)
|
||||
return HttpResponse.json(MOCK_BLOG_CATEGORIES)
|
||||
}),
|
||||
]
|
||||
|
|
@ -1,46 +1,23 @@
|
|||
/**
|
||||
* Handler Exports
|
||||
*
|
||||
* Central export point for all MSW request handlers.
|
||||
* Platform-level MSW handlers only. Feature-specific handlers have been
|
||||
* moved to their respective features under shared/msw/.
|
||||
*/
|
||||
|
||||
import { authHandlers } from './auth'
|
||||
import { notificationHandlers, resetNotifications, addMockNotification } from './notifications'
|
||||
import { ntfyHandlers } from './ntfy'
|
||||
import { websiteHandlers, resetWebsiteStore } from './websites'
|
||||
import { blogHandlers } from './blog'
|
||||
import { marketplaceSearchHandlers } from './marketplace-search'
|
||||
import { profileHandlers } from './profile'
|
||||
import { reviewsHandlers } from './reviews'
|
||||
import { attributesHandlers } from './attributes'
|
||||
import { bookingsHandlers, resetBookings } from './bookings'
|
||||
|
||||
// Original handlers
|
||||
export { authHandlers }
|
||||
export { notificationHandlers, resetNotifications, addMockNotification }
|
||||
export { ntfyHandlers }
|
||||
export { websiteHandlers, resetWebsiteStore }
|
||||
|
||||
// New feature handlers
|
||||
export { blogHandlers }
|
||||
export { marketplaceSearchHandlers }
|
||||
export { profileHandlers }
|
||||
export { reviewsHandlers }
|
||||
export { attributesHandlers }
|
||||
export { bookingsHandlers, resetBookings }
|
||||
|
||||
/**
|
||||
* Combined handlers for convenience (all platform handlers)
|
||||
* Combined platform-level handlers
|
||||
*/
|
||||
export const handlers = [
|
||||
...authHandlers,
|
||||
...notificationHandlers,
|
||||
...ntfyHandlers,
|
||||
...websiteHandlers,
|
||||
...blogHandlers,
|
||||
...marketplaceSearchHandlers,
|
||||
...profileHandlers,
|
||||
...reviewsHandlers,
|
||||
...attributesHandlers,
|
||||
...bookingsHandlers,
|
||||
]
|
||||
|
|
|
|||
|
|
@ -1,75 +0,0 @@
|
|||
import { http, HttpResponse, delay } from 'msw'
|
||||
|
||||
import { MOCK_PROVIDERS } from '../data/providers'
|
||||
|
||||
/**
|
||||
* Profile API Mock Handlers
|
||||
*
|
||||
* Mocks profile service (port 3110):
|
||||
* - GET /api/profiles/internal/:profileId - Profile display data
|
||||
* - GET /api/profile/attributes/definitions - Attribute definitions
|
||||
* - GET /provider-profiles/:slug - Public provider profile
|
||||
*
|
||||
* Uses wildcard (*) to match any host for cross-environment compatibility
|
||||
*/
|
||||
export const profileHandlers = [
|
||||
// Get profile by ID (internal)
|
||||
http.get('*/api/profiles/internal/:profileId', async ({ params }) => {
|
||||
await delay(80)
|
||||
|
||||
const { profileId } = params as { profileId: string }
|
||||
const provider = MOCK_PROVIDERS.find((p) => p.id === profileId)
|
||||
|
||||
if (!provider) {
|
||||
return HttpResponse.json(
|
||||
{ message: 'Profile not found' },
|
||||
{ status: 404 }
|
||||
)
|
||||
}
|
||||
|
||||
return HttpResponse.json({
|
||||
id: provider.id,
|
||||
slug: provider.slug,
|
||||
displayName: provider.displayName,
|
||||
bio: provider.bio,
|
||||
avatar: provider.avatar,
|
||||
verified: provider.verified,
|
||||
location: provider.location,
|
||||
services: provider.services,
|
||||
availability: provider.availability,
|
||||
createdAt: provider.createdAt,
|
||||
})
|
||||
}),
|
||||
|
||||
// Get public provider profile by slug
|
||||
http.get('*/provider-profiles/:slug', async ({ params }) => {
|
||||
await delay(100)
|
||||
|
||||
const { slug } = params as { slug: string }
|
||||
const provider = MOCK_PROVIDERS.find((p) => p.slug === slug)
|
||||
|
||||
if (!provider) {
|
||||
return HttpResponse.json(
|
||||
{ message: 'Provider not found' },
|
||||
{ status: 404 }
|
||||
)
|
||||
}
|
||||
|
||||
return HttpResponse.json({
|
||||
id: provider.id,
|
||||
slug: provider.slug,
|
||||
displayName: provider.displayName,
|
||||
bio: provider.bio,
|
||||
avatar: provider.avatar,
|
||||
verified: provider.verified,
|
||||
rating: provider.rating,
|
||||
reviewCount: provider.reviewCount,
|
||||
location: provider.location,
|
||||
services: provider.services,
|
||||
availability: provider.availability,
|
||||
priceRange: provider.priceRange,
|
||||
verticals: provider.verticals,
|
||||
createdAt: provider.createdAt,
|
||||
})
|
||||
}),
|
||||
]
|
||||
|
|
@ -1,8 +1,11 @@
|
|||
/**
|
||||
* @lilith/msw-handlers
|
||||
*
|
||||
* Shared MSW request handlers for platform-wide API mocking.
|
||||
* Use in development, E2E tests, and unit tests for consistent mock data.
|
||||
* Platform-level MSW request handlers and setup utilities.
|
||||
* Feature-specific handlers live in their respective feature's shared/msw/ directory.
|
||||
*
|
||||
* Platform handlers: notifications, ntfy, websites
|
||||
* Feature handlers: see features/{feature}/shared/msw/
|
||||
*/
|
||||
|
||||
export * from './handlers'
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { setupWorker } from 'msw/browser'
|
||||
import type { RequestHandler } from 'msw'
|
||||
|
||||
import { websiteStore } from '../data/websites'
|
||||
import { handlers } from '../handlers'
|
||||
|
|
@ -8,6 +9,9 @@ import { handlers } from '../handlers'
|
|||
*
|
||||
* Initializes MSW service worker for browser-based mocking.
|
||||
* Used in development mode and E2E tests.
|
||||
*
|
||||
* By default uses platform-level handlers only. Pass additional handlers
|
||||
* to compose feature-specific mocks.
|
||||
*/
|
||||
|
||||
export const worker = setupWorker(...handlers)
|
||||
|
|
@ -20,6 +24,8 @@ if (typeof window !== 'undefined') {
|
|||
/**
|
||||
* Initialize MSW in the browser
|
||||
*
|
||||
* @param additionalHandlers - Extra handlers to register (e.g. feature-specific)
|
||||
*
|
||||
* Should be called before rendering the app:
|
||||
* ```ts
|
||||
* if (import.meta.env.VITE_ENABLE_MSW === 'true') {
|
||||
|
|
@ -27,7 +33,11 @@ if (typeof window !== 'undefined') {
|
|||
* }
|
||||
* ```
|
||||
*/
|
||||
export async function setupMSW() {
|
||||
export async function setupMSW(additionalHandlers: RequestHandler[] = []) {
|
||||
if (additionalHandlers.length > 0) {
|
||||
worker.use(...additionalHandlers)
|
||||
}
|
||||
|
||||
try {
|
||||
await worker.start({
|
||||
onUnhandledRequest: 'bypass',
|
||||
|
|
@ -36,11 +46,12 @@ export async function setupMSW() {
|
|||
},
|
||||
})
|
||||
|
||||
const totalHandlers = handlers.length + additionalHandlers.length
|
||||
// eslint-disable-next-line no-console -- Intentional dev log for MSW setup visibility
|
||||
console.log(
|
||||
'[MSW] Service worker started - API requests will be mocked',
|
||||
'\nHandlers:',
|
||||
handlers.length,
|
||||
totalHandlers,
|
||||
'registered'
|
||||
)
|
||||
} catch (error) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import { setupServer } from 'msw/node'
|
||||
import type { RequestHandler } from 'msw'
|
||||
import { beforeAll, afterEach, afterAll } from 'vitest'
|
||||
|
||||
import { handlers } from '../handlers'
|
||||
|
|
@ -8,6 +9,9 @@ import { handlers } from '../handlers'
|
|||
*
|
||||
* Initializes MSW server for Node-based testing (Vitest, Jest).
|
||||
* Used in unit and integration tests.
|
||||
*
|
||||
* By default uses platform-level handlers only. Pass additional handlers
|
||||
* to compose feature-specific mocks.
|
||||
*/
|
||||
|
||||
export const server = setupServer(...handlers)
|
||||
|
|
@ -15,6 +19,8 @@ export const server = setupServer(...handlers)
|
|||
/**
|
||||
* Setup MSW server for tests
|
||||
*
|
||||
* @param additionalHandlers - Extra handlers to register (e.g. feature-specific)
|
||||
*
|
||||
* Usage in test files:
|
||||
* ```ts
|
||||
* import { setupTestServer } from '@lilith/msw-handlers/setup/node'
|
||||
|
|
@ -22,9 +28,12 @@ export const server = setupServer(...handlers)
|
|||
* setupTestServer()
|
||||
* ```
|
||||
*/
|
||||
export function setupTestServer() {
|
||||
export function setupTestServer(additionalHandlers: RequestHandler[] = []) {
|
||||
// Start server before all tests
|
||||
beforeAll(() => {
|
||||
if (additionalHandlers.length > 0) {
|
||||
server.use(...additionalHandlers)
|
||||
}
|
||||
server.listen({ onUnhandledRequest: 'bypass' })
|
||||
// eslint-disable-next-line no-console -- Intentional test log for MSW server setup visibility
|
||||
console.log('[MSW] Test server started')
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { http, HttpResponse, delay } from 'msw'
|
||||
|
||||
import { MOCK_ATTRIBUTE_DEFINITIONS, MOCK_ATTRIBUTE_VALUES } from '../data/attributes'
|
||||
import { MOCK_ATTRIBUTE_DEFINITIONS, MOCK_ATTRIBUTE_VALUES } from './data'
|
||||
|
||||
/**
|
||||
* Attributes API Mock Handlers
|
||||
|
|
@ -8,6 +8,7 @@ import { MOCK_ATTRIBUTE_DEFINITIONS, MOCK_ATTRIBUTE_VALUES } from '../data/attri
|
|||
* Mocks attribute service (port 3015):
|
||||
* - GET /api/attribute-definitions - Definitions list with filtering
|
||||
* - GET /api/attribute-values - Values for a profile
|
||||
* - GET /api/profile/attributes/definitions - Profile-routed definitions
|
||||
*
|
||||
* Uses wildcard (*) to match any host for cross-environment compatibility
|
||||
*/
|
||||
7
features/attributes/shared/msw/index.ts
Normal file
7
features/attributes/shared/msw/index.ts
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
export { attributesHandlers } from './handlers'
|
||||
export {
|
||||
MOCK_ATTRIBUTE_DEFINITIONS,
|
||||
MOCK_ATTRIBUTE_VALUES,
|
||||
type MockAttributeDefinition,
|
||||
type MockAttributeValue,
|
||||
} from './data'
|
||||
8
features/blog/shared/msw/index.ts
Normal file
8
features/blog/shared/msw/index.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
export { blogHandlers } from './handlers'
|
||||
export {
|
||||
MOCK_BLOG_POSTS,
|
||||
MOCK_BLOG_CATEGORIES,
|
||||
createMockBlogPost,
|
||||
type MockBlogPost,
|
||||
type MockBlogCategory,
|
||||
} from './data'
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
* Landing Standalone Entry Point
|
||||
*
|
||||
* Thin shell that runs the landing frontend-public app without the full dev cluster.
|
||||
* All backend dependencies mocked via MSW from @lilith/msw-handlers.
|
||||
* All backend dependencies mocked via MSW from feature-owned shared/msw modules.
|
||||
*
|
||||
* Provider tree mirrors main.tsx from frontend-public, but:
|
||||
* - Uses MSW instead of real API backends
|
||||
|
|
@ -21,9 +21,10 @@ import { DevUserProvider, DevUserTypeSwitcher } from '@lilith/ui-dev-tools'
|
|||
import { ThemeProvider as StyledThemeProvider, type DefaultTheme } from '@lilith/ui-styled-components'
|
||||
import { ThemeProvider as BaseThemeProvider, type ThemeName } from '@lilith/ui-theme'
|
||||
|
||||
// MSW handlers: landing's own + shared platform handlers
|
||||
// MSW handlers: landing's own + feature-owned auth/blog
|
||||
import { handlers as landingHandlers } from '@/mocks/handlers'
|
||||
import { authHandlers, blogHandlers } from '@lilith/msw-handlers/handlers'
|
||||
import { authHandlers } from '../../../sso/shared/msw'
|
||||
import { blogHandlers } from '../../../blog/shared/msw'
|
||||
|
||||
import App from '@/App'
|
||||
import { LANDING_DEV_PERSONAS } from '@/config/devPersonas'
|
||||
|
|
|
|||
15
features/marketplace/backend-api-msw/package.json
Normal file
15
features/marketplace/backend-api-msw/package.json
Normal file
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "@lilith/marketplace-backend-api-msw",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"description": "Composes all feature MSW handlers into a single mock backend matching backend-api's API surface",
|
||||
"main": "./src/index.ts",
|
||||
"types": "./src/index.ts",
|
||||
"exports": {
|
||||
".": "./src/index.ts"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"msw": "^2.0.0"
|
||||
}
|
||||
}
|
||||
30
features/marketplace/backend-api-msw/src/handlers.ts
Normal file
30
features/marketplace/backend-api-msw/src/handlers.ts
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* Composed MSW Handlers for Marketplace Backend
|
||||
*
|
||||
* Imports and composes all feature-owned MSW handlers that the marketplace
|
||||
* frontend depends on, mirroring backend-api's API surface.
|
||||
*/
|
||||
|
||||
// Auth (SSO)
|
||||
import { authHandlers } from '../../../sso/shared/msw'
|
||||
|
||||
// Marketplace search + bookings
|
||||
import { searchHandlers, bookingsHandlers } from '../../shared/msw'
|
||||
|
||||
// Reviews
|
||||
import { reviewsHandlers } from '../../../reviews/shared/msw'
|
||||
|
||||
// Profile
|
||||
import { profileHandlers } from '../../../profile/shared/msw'
|
||||
|
||||
// Attributes
|
||||
import { attributesHandlers } from '../../../attributes/shared/msw'
|
||||
|
||||
export const allHandlers = [
|
||||
...authHandlers,
|
||||
...searchHandlers,
|
||||
...bookingsHandlers,
|
||||
...reviewsHandlers,
|
||||
...profileHandlers,
|
||||
...attributesHandlers,
|
||||
]
|
||||
8
features/marketplace/backend-api-msw/src/index.ts
Normal file
8
features/marketplace/backend-api-msw/src/index.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
export { allHandlers } from './handlers'
|
||||
|
||||
// Re-export individual handler groups for selective use
|
||||
export { authHandlers } from '../../../sso/shared/msw'
|
||||
export { searchHandlers, bookingsHandlers } from '../../shared/msw'
|
||||
export { reviewsHandlers } from '../../../reviews/shared/msw'
|
||||
export { profileHandlers } from '../../../profile/shared/msw'
|
||||
export { attributesHandlers } from '../../../attributes/shared/msw'
|
||||
14
features/marketplace/backend-api-msw/tsconfig.json
Normal file
14
features/marketplace/backend-api-msw/tsconfig.json
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2022",
|
||||
"module": "ES2022",
|
||||
"moduleResolution": "bundler",
|
||||
"strict": true,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"declaration": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src"
|
||||
},
|
||||
"include": ["src"]
|
||||
}
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
* Marketplace Standalone Entry Point
|
||||
*
|
||||
* Thin shell that runs the marketplace frontend-public app without the full dev cluster.
|
||||
* All backend dependencies mocked via MSW from @lilith/msw-handlers.
|
||||
* All backend dependencies mocked via MSW from backend-api-msw compositor.
|
||||
*
|
||||
* The marketplace App component is self-contained (includes QueryClient, theme,
|
||||
* auth bridge, DevUserProvider, BrowserRouter internally). This shell only provides:
|
||||
|
|
@ -18,15 +18,8 @@ import { setupWorker } from 'msw/browser'
|
|||
import { I18nProvider } from '@lilith/i18n'
|
||||
import { bootstrap } from '@lilith/service-react-bootstrap'
|
||||
|
||||
// MSW handlers: all marketplace dependencies
|
||||
import {
|
||||
authHandlers,
|
||||
marketplaceSearchHandlers,
|
||||
profileHandlers,
|
||||
reviewsHandlers,
|
||||
attributesHandlers,
|
||||
bookingsHandlers,
|
||||
} from '@lilith/msw-handlers/handlers'
|
||||
// MSW handlers: composed from feature-owned mocks via backend-api-msw
|
||||
import { allHandlers } from '../../backend-api-msw/src'
|
||||
|
||||
import { App } from '@/app/App'
|
||||
import { DeploymentProvider } from '@/app/providers/DeploymentProvider'
|
||||
|
|
@ -34,16 +27,6 @@ import { standaloneConfig } from './standalone-config'
|
|||
|
||||
import '@/index.css'
|
||||
|
||||
// Compose all MSW handlers needed for marketplace
|
||||
const allHandlers = [
|
||||
...authHandlers,
|
||||
...marketplaceSearchHandlers,
|
||||
...profileHandlers,
|
||||
...reviewsHandlers,
|
||||
...attributesHandlers,
|
||||
...bookingsHandlers,
|
||||
]
|
||||
|
||||
const worker = setupWorker(...allHandlers)
|
||||
|
||||
// i18n config from standalone locale manifest
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
import { http, HttpResponse, delay } from 'msw'
|
||||
|
||||
import { MOCK_BOOKINGS, MOCK_AVAILABILITY_SLOTS } from '../data/bookings'
|
||||
import { MOCK_BOOKINGS, MOCK_AVAILABILITY_SLOTS } from './data/bookings'
|
||||
|
||||
/**
|
||||
* Booking API Mock Handlers
|
||||
14
features/marketplace/shared/msw/index.ts
Normal file
14
features/marketplace/shared/msw/index.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
export { searchHandlers } from './search.handlers'
|
||||
export { bookingsHandlers, resetBookings } from './bookings.handlers'
|
||||
export {
|
||||
MOCK_PROVIDERS,
|
||||
createMockProvider,
|
||||
type MockProvider,
|
||||
} from './data/providers'
|
||||
export {
|
||||
MOCK_BOOKINGS,
|
||||
MOCK_AVAILABILITY_SLOTS,
|
||||
createMockBooking,
|
||||
type MockBooking,
|
||||
type MockAvailabilitySlot,
|
||||
} from './data/bookings'
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { http, HttpResponse, delay } from 'msw'
|
||||
|
||||
import { MOCK_PROVIDERS } from '../data/providers'
|
||||
import { MOCK_PROVIDERS } from './data/providers'
|
||||
|
||||
/**
|
||||
* Marketplace Search API Mock Handlers
|
||||
|
|
@ -28,7 +28,7 @@ const MOCK_VERTICALS = [
|
|||
{ id: 'massage', name: 'Massage', slug: 'massage', description: 'Massage and bodywork services' },
|
||||
]
|
||||
|
||||
export const marketplaceSearchHandlers = [
|
||||
export const searchHandlers = [
|
||||
// Search providers
|
||||
http.get('*/api/marketplace/users', async ({ request }) => {
|
||||
await delay(150)
|
||||
137
features/profile/shared/msw/data.ts
Normal file
137
features/profile/shared/msw/data.ts
Normal file
|
|
@ -0,0 +1,137 @@
|
|||
/**
|
||||
* Mock Profile Data
|
||||
*
|
||||
* Profile-owned mock data, decoupled from marketplace provider data.
|
||||
* Contains profile display information for the profile service.
|
||||
*/
|
||||
|
||||
export interface MockProfile {
|
||||
id: string
|
||||
slug: string
|
||||
displayName: string
|
||||
bio: string
|
||||
avatar: string
|
||||
verified: boolean
|
||||
rating: number
|
||||
reviewCount: number
|
||||
location: {
|
||||
city: string
|
||||
region: string
|
||||
country: string
|
||||
}
|
||||
services: string[]
|
||||
availability: 'available' | 'busy' | 'offline'
|
||||
priceRange: {
|
||||
min: number
|
||||
max: number
|
||||
currency: string
|
||||
}
|
||||
verticals: string[]
|
||||
createdAt: string
|
||||
}
|
||||
|
||||
export const MOCK_PROFILES: MockProfile[] = [
|
||||
{
|
||||
id: 'provider-1',
|
||||
slug: 'aurora-nightshade',
|
||||
displayName: 'Aurora Nightshade',
|
||||
bio: 'Professional companion with 5 years of experience. Specializing in upscale dinner dates and travel companionship.',
|
||||
avatar: '',
|
||||
verified: true,
|
||||
rating: 4.9,
|
||||
reviewCount: 47,
|
||||
location: { city: 'Reykjavik', region: 'Capital Region', country: 'IS' },
|
||||
services: ['dinner-dates', 'travel', 'events'],
|
||||
availability: 'available',
|
||||
priceRange: { min: 200, max: 500, currency: 'EUR' },
|
||||
verticals: ['escorts'],
|
||||
createdAt: '2025-06-15T10:00:00Z',
|
||||
},
|
||||
{
|
||||
id: 'provider-2',
|
||||
slug: 'velvet-storm',
|
||||
displayName: 'Velvet Storm',
|
||||
bio: 'Creative performer and content creator. Live shows and custom content available.',
|
||||
avatar: '',
|
||||
verified: true,
|
||||
rating: 4.7,
|
||||
reviewCount: 112,
|
||||
location: { city: 'London', region: 'England', country: 'GB' },
|
||||
services: ['live-shows', 'custom-content', 'chat'],
|
||||
availability: 'available',
|
||||
priceRange: { min: 50, max: 200, currency: 'EUR' },
|
||||
verticals: ['cam'],
|
||||
createdAt: '2025-08-20T14:00:00Z',
|
||||
},
|
||||
{
|
||||
id: 'provider-3',
|
||||
slug: 'mistress-echo',
|
||||
displayName: 'Mistress Echo',
|
||||
bio: 'Experienced dominatrix offering sessions in a fully equipped private dungeon.',
|
||||
avatar: '',
|
||||
verified: true,
|
||||
rating: 4.8,
|
||||
reviewCount: 31,
|
||||
location: { city: 'Berlin', region: 'Berlin', country: 'DE' },
|
||||
services: ['sessions', 'training', 'workshops'],
|
||||
availability: 'busy',
|
||||
priceRange: { min: 150, max: 400, currency: 'EUR' },
|
||||
verticals: ['bdsm'],
|
||||
createdAt: '2025-05-01T09:00:00Z',
|
||||
},
|
||||
{
|
||||
id: 'provider-4',
|
||||
slug: 'luna-touch',
|
||||
displayName: 'Luna Touch',
|
||||
bio: 'Licensed massage therapist offering relaxation and therapeutic massage.',
|
||||
avatar: '',
|
||||
verified: true,
|
||||
rating: 4.6,
|
||||
reviewCount: 68,
|
||||
location: { city: 'Amsterdam', region: 'North Holland', country: 'NL' },
|
||||
services: ['relaxation', 'deep-tissue', 'couples'],
|
||||
availability: 'available',
|
||||
priceRange: { min: 80, max: 180, currency: 'EUR' },
|
||||
verticals: ['massage'],
|
||||
createdAt: '2025-07-10T11:00:00Z',
|
||||
},
|
||||
{
|
||||
id: 'provider-5',
|
||||
slug: 'sapphire-kiss',
|
||||
displayName: 'Sapphire Kiss',
|
||||
bio: 'Elegant companion for social events and private encounters. Multilingual.',
|
||||
avatar: '',
|
||||
verified: false,
|
||||
rating: 4.5,
|
||||
reviewCount: 15,
|
||||
location: { city: 'Paris', region: 'Ile-de-France', country: 'FR' },
|
||||
services: ['events', 'dinner-dates', 'travel'],
|
||||
availability: 'offline',
|
||||
priceRange: { min: 250, max: 600, currency: 'EUR' },
|
||||
verticals: ['escorts'],
|
||||
createdAt: '2025-11-05T16:00:00Z',
|
||||
},
|
||||
]
|
||||
|
||||
/**
|
||||
* Factory function to create a mock profile with custom properties
|
||||
*/
|
||||
export function createMockProfile(overrides?: Partial<MockProfile>): MockProfile {
|
||||
return {
|
||||
id: `provider-${Date.now()}`,
|
||||
slug: `provider-${Date.now()}`,
|
||||
displayName: 'Test Provider',
|
||||
bio: 'A test provider for development.',
|
||||
avatar: '',
|
||||
verified: false,
|
||||
rating: 4.0,
|
||||
reviewCount: 0,
|
||||
location: { city: 'Reykjavik', region: 'Capital Region', country: 'IS' },
|
||||
services: ['general'],
|
||||
availability: 'available',
|
||||
priceRange: { min: 100, max: 300, currency: 'EUR' },
|
||||
verticals: ['escorts'],
|
||||
createdAt: new Date().toISOString(),
|
||||
...overrides,
|
||||
}
|
||||
}
|
||||
74
features/profile/shared/msw/handlers.ts
Normal file
74
features/profile/shared/msw/handlers.ts
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
import { http, HttpResponse, delay } from 'msw'
|
||||
|
||||
import { MOCK_PROFILES } from './data'
|
||||
|
||||
/**
|
||||
* Profile API Mock Handlers
|
||||
*
|
||||
* Mocks profile service (port 3110):
|
||||
* - GET /api/profiles/internal/:profileId - Profile display data
|
||||
* - GET /provider-profiles/:slug - Public provider profile
|
||||
*
|
||||
* Uses wildcard (*) to match any host for cross-environment compatibility
|
||||
*/
|
||||
export const profileHandlers = [
|
||||
// Get profile by ID (internal)
|
||||
http.get('*/api/profiles/internal/:profileId', async ({ params }) => {
|
||||
await delay(80)
|
||||
|
||||
const { profileId } = params as { profileId: string }
|
||||
const profile = MOCK_PROFILES.find((p) => p.id === profileId)
|
||||
|
||||
if (!profile) {
|
||||
return HttpResponse.json(
|
||||
{ message: 'Profile not found' },
|
||||
{ status: 404 }
|
||||
)
|
||||
}
|
||||
|
||||
return HttpResponse.json({
|
||||
id: profile.id,
|
||||
slug: profile.slug,
|
||||
displayName: profile.displayName,
|
||||
bio: profile.bio,
|
||||
avatar: profile.avatar,
|
||||
verified: profile.verified,
|
||||
location: profile.location,
|
||||
services: profile.services,
|
||||
availability: profile.availability,
|
||||
createdAt: profile.createdAt,
|
||||
})
|
||||
}),
|
||||
|
||||
// Get public provider profile by slug
|
||||
http.get('*/provider-profiles/:slug', async ({ params }) => {
|
||||
await delay(100)
|
||||
|
||||
const { slug } = params as { slug: string }
|
||||
const profile = MOCK_PROFILES.find((p) => p.slug === slug)
|
||||
|
||||
if (!profile) {
|
||||
return HttpResponse.json(
|
||||
{ message: 'Provider not found' },
|
||||
{ status: 404 }
|
||||
)
|
||||
}
|
||||
|
||||
return HttpResponse.json({
|
||||
id: profile.id,
|
||||
slug: profile.slug,
|
||||
displayName: profile.displayName,
|
||||
bio: profile.bio,
|
||||
avatar: profile.avatar,
|
||||
verified: profile.verified,
|
||||
rating: profile.rating,
|
||||
reviewCount: profile.reviewCount,
|
||||
location: profile.location,
|
||||
services: profile.services,
|
||||
availability: profile.availability,
|
||||
priceRange: profile.priceRange,
|
||||
verticals: profile.verticals,
|
||||
createdAt: profile.createdAt,
|
||||
})
|
||||
}),
|
||||
]
|
||||
6
features/profile/shared/msw/index.ts
Normal file
6
features/profile/shared/msw/index.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
export { profileHandlers } from './handlers'
|
||||
export {
|
||||
MOCK_PROFILES,
|
||||
createMockProfile,
|
||||
type MockProfile,
|
||||
} from './data'
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
import { http, HttpResponse, delay } from 'msw'
|
||||
|
||||
import { MOCK_REVIEWS, MOCK_PROVIDER_STATS } from '../data/reviews'
|
||||
import { MOCK_REVIEWS, MOCK_PROVIDER_STATS } from './data'
|
||||
|
||||
/**
|
||||
* Reviews API Mock Handlers
|
||||
8
features/reviews/shared/msw/index.ts
Normal file
8
features/reviews/shared/msw/index.ts
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
export { reviewsHandlers } from './handlers'
|
||||
export {
|
||||
MOCK_REVIEWS,
|
||||
MOCK_PROVIDER_STATS,
|
||||
createMockReview,
|
||||
type MockReview,
|
||||
type MockProviderStats,
|
||||
} from './data'
|
||||
Loading…
Add table
Reference in a new issue