Refactor Dockerfile and server code to improve TypeScript build process, enhance health check compatibility, and streamline mock API structure. Update hooks for script management to include user ID in create and update operations, ensuring better integration with the API.
This commit is contained in:
@ -23,6 +23,24 @@
|
|||||||
**Problem**: Health check trying to access `/health` endpoint that doesn't exist
|
**Problem**: Health check trying to access `/health` endpoint that doesn't exist
|
||||||
**Fix Applied**: Changed health check to use root path `/` which always exists for Nginx
|
**Fix Applied**: Changed health check to use root path `/` which always exists for Nginx
|
||||||
|
|
||||||
|
### **Issue 4: Mock API Build Order & TypeScript Errors** ❌→✅
|
||||||
|
**Problem**:
|
||||||
|
- TypeScript compilation errors in mock API functions
|
||||||
|
- Build order issue: source files copied before mock API creation
|
||||||
|
- Server.ts file causing compilation errors
|
||||||
|
|
||||||
|
**Root Cause**:
|
||||||
|
- Mock API files created after source code copy
|
||||||
|
- TypeScript compilation happening before mock API is ready
|
||||||
|
- Server.ts file not needed for frontend demo
|
||||||
|
|
||||||
|
**Fix Applied**:
|
||||||
|
1. Reordered Dockerfile: create mock API structure BEFORE copying source code
|
||||||
|
2. Added `rm -f src/server.ts` to remove server file
|
||||||
|
3. Fixed function signatures in mock API (added missing parameters)
|
||||||
|
4. Fixed useCreateScript hook to properly handle userId parameter
|
||||||
|
5. Fixed server.ts createScript call to pass userId parameter
|
||||||
|
|
||||||
## 📋 Changes Made
|
## 📋 Changes Made
|
||||||
|
|
||||||
### **1. Updated Dockerfile (Lines 77, 89, 113)**
|
### **1. Updated Dockerfile (Lines 77, 89, 113)**
|
||||||
@ -42,9 +60,11 @@ CMD curl -f http://localhost/ || wget -q --spider http://localhost/ || exit 1
|
|||||||
After these fixes:
|
After these fixes:
|
||||||
|
|
||||||
1. **TypeScript Build**: ✅ Should compile `.tsx` files successfully
|
1. **TypeScript Build**: ✅ Should compile `.tsx` files successfully
|
||||||
2. **Health Check**: ✅ Should pass using either curl or wget
|
2. **Mock API**: ✅ Should compile without TypeScript errors
|
||||||
3. **Container Status**: ✅ Should show as healthy
|
3. **Health Check**: ✅ Should pass using either curl or wget
|
||||||
4. **Deployment**: ✅ Should complete without rollback
|
4. **Container Status**: ✅ Should show as healthy
|
||||||
|
5. **Deployment**: ✅ Should complete without rollback
|
||||||
|
6. **Frontend**: ✅ Should load and function properly with mock API
|
||||||
|
|
||||||
## 🎯 Root Cause Analysis
|
## 🎯 Root Cause Analysis
|
||||||
|
|
||||||
|
11
Dockerfile
11
Dockerfile
@ -12,9 +12,6 @@ COPY package*.json ./
|
|||||||
# Install dependencies with proper npm cache handling
|
# Install dependencies with proper npm cache handling
|
||||||
RUN npm ci --only=production=false --silent
|
RUN npm ci --only=production=false --silent
|
||||||
|
|
||||||
# Copy source code
|
|
||||||
COPY . .
|
|
||||||
|
|
||||||
# Set build-time environment variables
|
# Set build-time environment variables
|
||||||
ARG VITE_APP_NAME="ScriptShare"
|
ARG VITE_APP_NAME="ScriptShare"
|
||||||
ARG VITE_APP_URL="https://scriptshare.example.com"
|
ARG VITE_APP_URL="https://scriptshare.example.com"
|
||||||
@ -39,10 +36,14 @@ RUN npm install
|
|||||||
# Remove problematic server-side API files for frontend-only build
|
# Remove problematic server-side API files for frontend-only build
|
||||||
RUN rm -rf src/lib/api || true
|
RUN rm -rf src/lib/api || true
|
||||||
RUN rm -rf src/lib/db || true
|
RUN rm -rf src/lib/db || true
|
||||||
|
RUN rm -f src/server.ts || true
|
||||||
|
|
||||||
# Create mock API layer for frontend demo
|
# Create mock API layer for frontend demo
|
||||||
RUN mkdir -p src/lib/api src/lib/db
|
RUN mkdir -p src/lib/api src/lib/db
|
||||||
|
|
||||||
|
# Copy source code AFTER creating mock API structure
|
||||||
|
COPY . .
|
||||||
|
|
||||||
# Create mock database files
|
# Create mock database files
|
||||||
RUN echo "export const db = {};" > src/lib/db/index.ts
|
RUN echo "export const db = {};" > src/lib/db/index.ts
|
||||||
RUN echo "export const users = {}; export const scripts = {}; export const ratings = {}; export const scriptVersions = {}; export const scriptAnalytics = {}; export const scriptCollections = {}; export const collectionScripts = {};" > src/lib/db/schema.ts
|
RUN echo "export const users = {}; export const scripts = {}; export const ratings = {}; export const scriptVersions = {}; export const scriptAnalytics = {}; export const scriptCollections = {}; export const collectionScripts = {};" > src/lib/db/schema.ts
|
||||||
@ -56,7 +57,7 @@ RUN printf 'import { nanoid } from "nanoid";\nexport const generateId = () => na
|
|||||||
RUN printf 'export interface LoginCredentials {\n email: string;\n password: string;\n}\nexport interface RegisterData {\n email: string;\n username: string;\n displayName: string;\n password: string;\n}\nexport interface AuthToken {\n token: string;\n user: any;\n}\nexport async function login(credentials: LoginCredentials): Promise<AuthToken> {\n return { token: "demo-token", user: { id: "1", username: "demo", email: "demo@example.com", displayName: "Demo User", isAdmin: false, isModerator: false } };\n}\nexport async function register(data: RegisterData): Promise<AuthToken> {\n return { token: "demo-token", user: { id: "1", username: data.username, email: data.email, displayName: data.displayName, isAdmin: false, isModerator: false } };\n}\nexport async function refreshToken(token: string): Promise<AuthToken> {\n return { token: "demo-token", user: { id: "1", username: "demo", email: "demo@example.com", displayName: "Demo User", isAdmin: false, isModerator: false } };\n}\nexport async function changePassword(userId: string, currentPassword: string, newPassword: string): Promise<boolean> {\n return true;\n}' > src/lib/api/auth.ts
|
RUN printf 'export interface LoginCredentials {\n email: string;\n password: string;\n}\nexport interface RegisterData {\n email: string;\n username: string;\n displayName: string;\n password: string;\n}\nexport interface AuthToken {\n token: string;\n user: any;\n}\nexport async function login(credentials: LoginCredentials): Promise<AuthToken> {\n return { token: "demo-token", user: { id: "1", username: "demo", email: "demo@example.com", displayName: "Demo User", isAdmin: false, isModerator: false } };\n}\nexport async function register(data: RegisterData): Promise<AuthToken> {\n return { token: "demo-token", user: { id: "1", username: data.username, email: data.email, displayName: data.displayName, isAdmin: false, isModerator: false } };\n}\nexport async function refreshToken(token: string): Promise<AuthToken> {\n return { token: "demo-token", user: { id: "1", username: "demo", email: "demo@example.com", displayName: "Demo User", isAdmin: false, isModerator: false } };\n}\nexport async function changePassword(userId: string, currentPassword: string, newPassword: string): Promise<boolean> {\n return true;\n}' > src/lib/api/auth.ts
|
||||||
|
|
||||||
# Mock scripts API with individual function exports
|
# Mock scripts API with individual function exports
|
||||||
RUN printf 'export interface ScriptFilters {\n search?: string;\n categories?: string[];\n compatibleOs?: string[];\n sortBy?: string;\n limit?: number;\n isApproved?: boolean;\n}\nexport interface UpdateScriptData {\n name?: string;\n description?: string;\n content?: string;\n}\nexport interface CreateScriptData {\n name: string;\n description: string;\n content: string;\n categories: string[];\n compatibleOs: string[];\n tags?: string[];\n}\nexport async function getScripts(filters?: ScriptFilters) {\n return { scripts: [], total: 0 };\n}\nexport async function getScriptById(id: string) {\n return null;\n}\nexport async function getPopularScripts() {\n return [];\n}\nexport async function getRecentScripts() {\n return [];\n}\nexport async function createScript(data: CreateScriptData, userId: string) {\n return { id: "mock-script-id", ...data, authorId: userId };\n}\nexport async function updateScript(id: string, data: UpdateScriptData, userId: string) {\n return { id, ...data };\n}\nexport async function deleteScript(id: string, userId: string) {\n return { success: true };\n}\nexport async function moderateScript(id: string, isApproved: boolean, moderatorId: string) {\n return { id, isApproved };\n}\nexport async function incrementViewCount(id: string) {\n return { success: true };\n}\nexport async function incrementDownloadCount(id: string) {\n return { success: true };\n}' > src/lib/api/scripts.ts
|
RUN printf 'export interface ScriptFilters {\n search?: string;\n categories?: string[];\n compatibleOs?: string[];\n sortBy?: string;\n limit?: number;\n isApproved?: boolean;\n}\nexport interface UpdateScriptData {\n name?: string;\n description?: string;\n content?: string;\n}\nexport interface CreateScriptData {\n name: string;\n description: string;\n content: string;\n categories: string[];\n compatibleOs: string[];\n tags?: string[];\n}\nexport async function getScripts(filters?: ScriptFilters) {\n return { scripts: [], total: 0 };\n}\nexport async function getScriptById(id: string) {\n return null;\n}\nexport async function getPopularScripts(limit?: number) {\n return [];\n}\nexport async function getRecentScripts(limit?: number) {\n return [];\n}\nexport async function createScript(data: CreateScriptData, userId: string) {\n return { id: "mock-script-id", ...data, authorId: userId };\n}\nexport async function updateScript(id: string, data: UpdateScriptData, userId: string) {\n return { id, ...data };\n}\nexport async function deleteScript(id: string, userId: string) {\n return { success: true };\n}\nexport async function moderateScript(id: string, isApproved: boolean, moderatorId: string) {\n return { id, isApproved };\n}\nexport async function incrementViewCount(id: string) {\n return { success: true };\n}\nexport async function incrementDownloadCount(id: string) {\n return { success: true };\n}' > src/lib/api/scripts.ts
|
||||||
|
|
||||||
# Mock ratings API with individual function exports
|
# Mock ratings API with individual function exports
|
||||||
RUN printf 'export interface CreateRatingData {\n scriptId: string;\n userId: string;\n rating: number;\n}\nexport async function rateScript(data: CreateRatingData) {\n return { id: "mock-rating-id", ...data, createdAt: new Date(), updatedAt: new Date() };\n}\nexport async function getUserRating(scriptId: string, userId: string) {\n return null;\n}\nexport async function getScriptRatings(scriptId: string) {\n return [];\n}\nexport async function getScriptRatingStats(scriptId: string) {\n return { averageRating: 0, totalRatings: 0, distribution: [] };\n}\nexport async function deleteRating(scriptId: string, userId: string) {\n return { success: true };\n}' > src/lib/api/ratings.ts
|
RUN printf 'export interface CreateRatingData {\n scriptId: string;\n userId: string;\n rating: number;\n}\nexport async function rateScript(data: CreateRatingData) {\n return { id: "mock-rating-id", ...data, createdAt: new Date(), updatedAt: new Date() };\n}\nexport async function getUserRating(scriptId: string, userId: string) {\n return null;\n}\nexport async function getScriptRatings(scriptId: string) {\n return [];\n}\nexport async function getScriptRatingStats(scriptId: string) {\n return { averageRating: 0, totalRatings: 0, distribution: [] };\n}\nexport async function deleteRating(scriptId: string, userId: string) {\n return { success: true };\n}' > src/lib/api/ratings.ts
|
||||||
@ -65,7 +66,7 @@ RUN printf 'export interface CreateRatingData {\n scriptId: string;\n userId:
|
|||||||
RUN printf 'export interface TrackEventData {\n scriptId: string;\n eventType: string;\n userId?: string;\n userAgent?: string;\n ipAddress?: string;\n referrer?: string;\n}\nexport interface AnalyticsFilters {\n scriptId?: string;\n eventType?: string;\n startDate?: Date;\n endDate?: Date;\n userId?: string;\n}\nexport async function trackEvent(data: TrackEventData) {\n return { success: true };\n}\nexport async function getAnalyticsEvents(filters?: AnalyticsFilters) {\n return [];\n}\nexport async function getScriptAnalytics(scriptId: string, days?: number) {\n return { eventCounts: [], dailyActivity: [], referrers: [], periodDays: days || 30 };\n}\nexport async function getPlatformAnalytics(days?: number) {\n return { totals: { totalScripts: 0, approvedScripts: 0, pendingScripts: 0 }, activityByType: [], popularScripts: [], dailyTrends: [], periodDays: days || 30 };\n}\nexport async function getUserAnalytics(userId: string, days?: number) {\n return { userScripts: [], recentActivity: [], periodDays: days || 30 };\n}' > src/lib/api/analytics.ts
|
RUN printf 'export interface TrackEventData {\n scriptId: string;\n eventType: string;\n userId?: string;\n userAgent?: string;\n ipAddress?: string;\n referrer?: string;\n}\nexport interface AnalyticsFilters {\n scriptId?: string;\n eventType?: string;\n startDate?: Date;\n endDate?: Date;\n userId?: string;\n}\nexport async function trackEvent(data: TrackEventData) {\n return { success: true };\n}\nexport async function getAnalyticsEvents(filters?: AnalyticsFilters) {\n return [];\n}\nexport async function getScriptAnalytics(scriptId: string, days?: number) {\n return { eventCounts: [], dailyActivity: [], referrers: [], periodDays: days || 30 };\n}\nexport async function getPlatformAnalytics(days?: number) {\n return { totals: { totalScripts: 0, approvedScripts: 0, pendingScripts: 0 }, activityByType: [], popularScripts: [], dailyTrends: [], periodDays: days || 30 };\n}\nexport async function getUserAnalytics(userId: string, days?: number) {\n return { userScripts: [], recentActivity: [], periodDays: days || 30 };\n}' > src/lib/api/analytics.ts
|
||||||
|
|
||||||
# Mock collections API with individual function exports
|
# Mock collections API with individual function exports
|
||||||
RUN printf 'export interface CreateCollectionData {\n name: string;\n description?: string;\n authorId: string;\n isPublic?: boolean;\n}\nexport interface UpdateCollectionData {\n name?: string;\n description?: string;\n isPublic?: boolean;\n}\nexport async function createCollection(data: CreateCollectionData) {\n return { id: "mock-collection-id", ...data, createdAt: new Date(), updatedAt: new Date() };\n}\nexport async function getCollectionById(id: string) {\n return null;\n}\nexport async function getUserCollections(userId: string) {\n return [];\n}\nexport async function getPublicCollections(limit?: number, offset?: number) {\n return [];\n}\nexport async function updateCollection(id: string, data: UpdateCollectionData, userId: string) {\n return { id, ...data, updatedAt: new Date() };\n}\nexport async function deleteCollection(id: string, userId: string) {\n return { success: true };\n}\nexport async function addScriptToCollection(collectionId: string, scriptId: string, userId: string) {\n return { id: "mock-collection-script-id", collectionId, scriptId, addedAt: new Date() };\n}\nexport async function removeScriptFromCollection(collectionId: string, scriptId: string, userId: string) {\n return { success: true };\n}\nexport async function isScriptInCollection(collectionId: string, scriptId: string) {\n return false;\n}' > src/lib/api/collections.ts
|
RUN printf 'export interface CreateCollectionData {\n name: string;\n description?: string;\n authorId: string;\n isPublic?: boolean;\n}\nexport interface UpdateCollectionData {\n name?: string;\n description?: string;\n isPublic?: boolean;\n}\nexport async function createCollection(data: CreateCollectionData) {\n return { id: "mock-collection-id", ...data, createdAt: new Date(), updatedAt: new Date() };\n}\nexport async function getCollectionById(id: string) {\n return null;\n}\nexport async function getUserCollections(userId: string) {\n return [];\n}\nexport async function getPublicCollections(limit?: number, offset?: number) {\n return [];\n}\nexport async function updateCollection(id: string, data: UpdateCollectionData, userId: string) {\n return { id, ...data, authorId: userId, updatedAt: new Date() };\n}\nexport async function deleteCollection(id: string, userId: string) {\n return { success: true };\n}\nexport async function addScriptToCollection(collectionId: string, scriptId: string, userId: string) {\n return { id: "mock-collection-script-id", collectionId, scriptId, addedAt: new Date() };\n}\nexport async function removeScriptFromCollection(collectionId: string, scriptId: string, userId: string) {\n return { success: true };\n}\nexport async function isScriptInCollection(collectionId: string, scriptId: string) {\n return false;\n}' > src/lib/api/collections.ts
|
||||||
|
|
||||||
# Mock users API with individual function exports
|
# Mock users API with individual function exports
|
||||||
RUN printf 'export interface CreateUserData {\n email: string;\n username: string;\n displayName: string;\n avatarUrl?: string;\n bio?: string;\n}\nexport interface UpdateUserData {\n username?: string;\n displayName?: string;\n avatarUrl?: string;\n bio?: string;\n}\nexport async function createUser(data: CreateUserData) {\n return { id: "mock-user-id", ...data, isAdmin: false, isModerator: false, createdAt: new Date(), updatedAt: new Date() };\n}\nexport async function getUserById(id: string) {\n return null;\n}\nexport async function getUserByEmail(email: string) {\n return null;\n}\nexport async function getUserByUsername(username: string) {\n return null;\n}\nexport async function updateUser(id: string, data: UpdateUserData) {\n return { id, ...data, updatedAt: new Date() };\n}\nexport async function updateUserPermissions(id: string, permissions: any) {\n return { id, ...permissions, updatedAt: new Date() };\n}\nexport async function searchUsers(query: string, limit?: number) {\n return [];\n}\nexport async function getAllUsers(limit?: number, offset?: number) {\n return [];\n}' > src/lib/api/users.ts
|
RUN printf 'export interface CreateUserData {\n email: string;\n username: string;\n displayName: string;\n avatarUrl?: string;\n bio?: string;\n}\nexport interface UpdateUserData {\n username?: string;\n displayName?: string;\n avatarUrl?: string;\n bio?: string;\n}\nexport async function createUser(data: CreateUserData) {\n return { id: "mock-user-id", ...data, isAdmin: false, isModerator: false, createdAt: new Date(), updatedAt: new Date() };\n}\nexport async function getUserById(id: string) {\n return null;\n}\nexport async function getUserByEmail(email: string) {\n return null;\n}\nexport async function getUserByUsername(username: string) {\n return null;\n}\nexport async function updateUser(id: string, data: UpdateUserData) {\n return { id, ...data, updatedAt: new Date() };\n}\nexport async function updateUserPermissions(id: string, permissions: any) {\n return { id, ...permissions, updatedAt: new Date() };\n}\nexport async function searchUsers(query: string, limit?: number) {\n return [];\n}\nexport async function getAllUsers(limit?: number, offset?: number) {\n return [];\n}' > src/lib/api/users.ts
|
||||||
|
@ -55,7 +55,8 @@ export function useCreateScript() {
|
|||||||
const queryClient = useQueryClient();
|
const queryClient = useQueryClient();
|
||||||
|
|
||||||
return useMutation({
|
return useMutation({
|
||||||
mutationFn: scriptsApi.createScript,
|
mutationFn: ({ data, userId }: { data: scriptsApi.CreateScriptData; userId: string }) =>
|
||||||
|
scriptsApi.createScript(data, userId),
|
||||||
onSuccess: () => {
|
onSuccess: () => {
|
||||||
queryClient.invalidateQueries({ queryKey: scriptKeys.lists() });
|
queryClient.invalidateQueries({ queryKey: scriptKeys.lists() });
|
||||||
showSuccess('Script created successfully!');
|
showSuccess('Script created successfully!');
|
||||||
|
@ -74,7 +74,7 @@ app.post('/api/scripts', async (req: Request, res: Response) => {
|
|||||||
if (!userId) {
|
if (!userId) {
|
||||||
return res.status(401).json({ error: 'Unauthorized' });
|
return res.status(401).json({ error: 'Unauthorized' });
|
||||||
}
|
}
|
||||||
const result = await createScript(req.body);
|
const result = await createScript(req.body, userId);
|
||||||
res.json(result);
|
res.json(result);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Create script error:', error);
|
console.error('Create script error:', error);
|
||||||
|
Reference in New Issue
Block a user