Spaces:
Sleeping
Sleeping
Commit ·
86c1aaf
1
Parent(s): 0d07c0a
apply changes
Browse files- src/app/api/sync/run/route.ts +22 -14
- src/app/api/sync/status/route.ts +19 -45
- src/db/schema.ts +8 -4
- src/lib/auth.ts +13 -3
src/app/api/sync/run/route.ts
CHANGED
|
@@ -23,6 +23,9 @@ export async function POST(request: NextRequest) {
|
|
| 23 |
return NextResponse.json({ error: "GitHub access token not found" }, { status: 400 });
|
| 24 |
}
|
| 25 |
|
|
|
|
|
|
|
|
|
|
| 26 |
// Get current user record to check sync status
|
| 27 |
const userRecord = await db.select()
|
| 28 |
.from(users)
|
|
@@ -61,6 +64,7 @@ export async function POST(request: NextRequest) {
|
|
| 61 |
syncError: null
|
| 62 |
})
|
| 63 |
.where(eq(users.id, user.id));
|
|
|
|
| 64 |
|
| 65 |
console.log(`[SyncRun] Starting sync for user ${user.id}`);
|
| 66 |
|
|
@@ -85,14 +89,15 @@ export async function POST(request: NextRequest) {
|
|
| 85 |
// Always reconcile the critical openTriage#1 issue to ensure immediate state sync
|
| 86 |
const reconcileResult = await reconcileOpenTriageIssue1(user.githubAccessToken);
|
| 87 |
|
|
|
|
|
|
|
| 88 |
// Mark sync as COMPLETED
|
| 89 |
-
await db.update(users)
|
| 90 |
-
|
| 91 |
-
|
| 92 |
-
|
| 93 |
-
|
| 94 |
-
|
| 95 |
-
.where(eq(users.id, user.id));
|
| 96 |
|
| 97 |
console.log(`[SyncRun] Sync completed for user ${user.id}`);
|
| 98 |
|
|
@@ -109,13 +114,16 @@ export async function POST(request: NextRequest) {
|
|
| 109 |
});
|
| 110 |
|
| 111 |
} catch (syncError: any) {
|
| 112 |
-
|
| 113 |
-
|
| 114 |
-
|
| 115 |
-
|
| 116 |
-
|
| 117 |
-
|
| 118 |
-
|
|
|
|
|
|
|
|
|
|
| 119 |
|
| 120 |
console.error(`[SyncRun] Sync failed for user ${user.id}:`, syncError);
|
| 121 |
|
|
|
|
| 23 |
return NextResponse.json({ error: "GitHub access token not found" }, { status: 400 });
|
| 24 |
}
|
| 25 |
|
| 26 |
+
// TODO: Uncomment after Turso migration
|
| 27 |
+
// Circuit breaker logic commented out until sync_status column exists in production
|
| 28 |
+
/*
|
| 29 |
// Get current user record to check sync status
|
| 30 |
const userRecord = await db.select()
|
| 31 |
.from(users)
|
|
|
|
| 64 |
syncError: null
|
| 65 |
})
|
| 66 |
.where(eq(users.id, user.id));
|
| 67 |
+
*/
|
| 68 |
|
| 69 |
console.log(`[SyncRun] Starting sync for user ${user.id}`);
|
| 70 |
|
|
|
|
| 89 |
// Always reconcile the critical openTriage#1 issue to ensure immediate state sync
|
| 90 |
const reconcileResult = await reconcileOpenTriageIssue1(user.githubAccessToken);
|
| 91 |
|
| 92 |
+
// TODO: Uncomment after Turso migration
|
| 93 |
+
/*
|
| 94 |
// Mark sync as COMPLETED
|
| 95 |
+
await db.update(users).set({
|
| 96 |
+
syncStatus: 'COMPLETED',
|
| 97 |
+
lastSyncAt: new Date().toISOString(),
|
| 98 |
+
syncError: null
|
| 99 |
+
}).where(eq(users.id, user.id));
|
| 100 |
+
*/
|
|
|
|
| 101 |
|
| 102 |
console.log(`[SyncRun] Sync completed for user ${user.id}`);
|
| 103 |
|
|
|
|
| 114 |
});
|
| 115 |
|
| 116 |
} catch (syncError: any) {
|
| 117 |
+
console.error(`[SyncRun] Error syncing for user ${user.id}:`, syncError);
|
| 118 |
+
|
| 119 |
+
// TODO: Uncomment after Turso migration
|
| 120 |
+
/*
|
| 121 |
+
// Mark sync as FAILED
|
| 122 |
+
await db.update(users).set({
|
| 123 |
+
syncStatus: 'FAILED',
|
| 124 |
+
syncError: syncError.message || 'Unknown error'
|
| 125 |
+
}).where(eq(users.id, user.id));
|
| 126 |
+
*/
|
| 127 |
|
| 128 |
console.error(`[SyncRun] Sync failed for user ${user.id}:`, syncError);
|
| 129 |
|
src/app/api/sync/status/route.ts
CHANGED
|
@@ -1,51 +1,25 @@
|
|
| 1 |
/**
|
| 2 |
-
*
|
| 3 |
*
|
| 4 |
-
*
|
| 5 |
-
*
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6 |
*/
|
| 7 |
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
| 19 |
-
}
|
| 20 |
-
|
| 21 |
-
// Get user's sync status
|
| 22 |
-
const userRecord = await db.select({
|
| 23 |
-
syncStatus: users.syncStatus,
|
| 24 |
-
lastSyncAt: users.lastSyncAt,
|
| 25 |
-
syncError: users.syncError,
|
| 26 |
-
})
|
| 27 |
-
.from(users)
|
| 28 |
-
.where(eq(users.id, user.id))
|
| 29 |
-
.limit(1);
|
| 30 |
-
|
| 31 |
-
if (!userRecord || userRecord.length === 0) {
|
| 32 |
-
return NextResponse.json({ error: "User not found" }, { status: 404 });
|
| 33 |
}
|
| 34 |
-
|
| 35 |
-
const { syncStatus, lastSyncAt, syncError } = userRecord[0];
|
| 36 |
-
|
| 37 |
-
return NextResponse.json({
|
| 38 |
-
status: syncStatus || 'IDLE',
|
| 39 |
-
lastSyncAt: lastSyncAt || null,
|
| 40 |
-
error: syncError || null,
|
| 41 |
-
isIdl: syncStatus === 'IDLE' || syncStatus === 'COMPLETED',
|
| 42 |
-
isSyncing: syncStatus === 'SYNCING',
|
| 43 |
-
isPending: syncStatus === 'PENDING',
|
| 44 |
-
hasFailed: syncStatus === 'FAILED',
|
| 45 |
-
});
|
| 46 |
-
|
| 47 |
-
} catch (error) {
|
| 48 |
-
console.error("GET /api/sync/status error:", error);
|
| 49 |
-
return NextResponse.json({ error: "Internal server error" }, { status: 500 });
|
| 50 |
-
}
|
| 51 |
}
|
|
|
|
| 1 |
/**
|
| 2 |
+
* TODO: Re-enable after Turso migration
|
| 3 |
*
|
| 4 |
+
* This endpoint is temporarily disabled because it queries sync_status columns
|
| 5 |
+
* that don't exist in the production Turso database yet.
|
| 6 |
+
*
|
| 7 |
+
* To re-enable:
|
| 8 |
+
* 1. Run migration: add_sync_status.sql on Turso
|
| 9 |
+
* 2. Uncomment the code below
|
| 10 |
+
* 3. Deploy
|
| 11 |
*/
|
| 12 |
|
| 13 |
+
// Endpoint disabled until migration
|
| 14 |
+
export function GET() {
|
| 15 |
+
return new Response(
|
| 16 |
+
JSON.stringify({
|
| 17 |
+
error: "Endpoint temporarily disabled",
|
| 18 |
+
message: "Sync status tracking not yet available"
|
| 19 |
+
}),
|
| 20 |
+
{
|
| 21 |
+
status: 503,
|
| 22 |
+
headers: { 'Content-Type': 'application/json' }
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 23 |
}
|
| 24 |
+
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 25 |
}
|
src/db/schema.ts
CHANGED
|
@@ -36,11 +36,15 @@ export const users = sqliteTable("users", {
|
|
| 36 |
githubId: integer("github_id").unique().notNull(),
|
| 37 |
username: text("username").notNull(),
|
| 38 |
avatarUrl: text("avatar_url").notNull(),
|
| 39 |
-
role: text("role"), //
|
| 40 |
githubAccessToken: text("github_access_token"),
|
| 41 |
-
|
| 42 |
-
|
| 43 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 44 |
createdAt: text("created_at").notNull(),
|
| 45 |
updatedAt: text("updated_at").notNull(),
|
| 46 |
});
|
|
|
|
| 36 |
githubId: integer("github_id").unique().notNull(),
|
| 37 |
username: text("username").notNull(),
|
| 38 |
avatarUrl: text("avatar_url").notNull(),
|
| 39 |
+
role: text("role"), // email: text("email"),
|
| 40 |
githubAccessToken: text("github_access_token"),
|
| 41 |
+
|
| 42 |
+
// TODO: Uncomment after running Turso migration (add_sync_status.sql)
|
| 43 |
+
// Sync status tracking (Phase 2)
|
| 44 |
+
// syncStatus: text("sync_status").default("IDLE"), // IDLE | PENDING | SYNCING | COMPLETED | FAILED
|
| 45 |
+
// lastSyncAt: text("last_sync_at"), // ISO timestamp
|
| 46 |
+
// syncError: text("sync_error"), // Error message if failed
|
| 47 |
+
|
| 48 |
createdAt: text("created_at").notNull(),
|
| 49 |
updatedAt: text("updated_at").notNull(),
|
| 50 |
});
|
src/lib/auth.ts
CHANGED
|
@@ -38,7 +38,7 @@ export function verifyJwtToken(token: string): { user_id: string; role: string |
|
|
| 38 |
*/
|
| 39 |
export async function getCurrentUser(request: NextRequest) {
|
| 40 |
let token: string | null = null;
|
| 41 |
-
|
| 42 |
// Try Authorization header first
|
| 43 |
const authHeader = request.headers.get("Authorization");
|
| 44 |
console.log("[getCurrentUser] Authorization header:", authHeader ? "Present" : "Missing");
|
|
@@ -46,7 +46,7 @@ export async function getCurrentUser(request: NextRequest) {
|
|
| 46 |
token = authHeader.substring(7);
|
| 47 |
console.log("[getCurrentUser] Found token in Authorization header");
|
| 48 |
}
|
| 49 |
-
|
| 50 |
// Fallback to query param for SSE connections
|
| 51 |
if (!token) {
|
| 52 |
const url = new URL(request.url);
|
|
@@ -66,8 +66,18 @@ export async function getCurrentUser(request: NextRequest) {
|
|
| 66 |
console.log("[getCurrentUser] Token verified, user_id:", payload.user_id);
|
| 67 |
|
| 68 |
// Fetch full user from database
|
|
|
|
| 69 |
const userRecords = await db
|
| 70 |
-
.select(
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 71 |
.from(users)
|
| 72 |
.where(eq(users.id, payload.user_id))
|
| 73 |
.limit(1);
|
|
|
|
| 38 |
*/
|
| 39 |
export async function getCurrentUser(request: NextRequest) {
|
| 40 |
let token: string | null = null;
|
| 41 |
+
|
| 42 |
// Try Authorization header first
|
| 43 |
const authHeader = request.headers.get("Authorization");
|
| 44 |
console.log("[getCurrentUser] Authorization header:", authHeader ? "Present" : "Missing");
|
|
|
|
| 46 |
token = authHeader.substring(7);
|
| 47 |
console.log("[getCurrentUser] Found token in Authorization header");
|
| 48 |
}
|
| 49 |
+
|
| 50 |
// Fallback to query param for SSE connections
|
| 51 |
if (!token) {
|
| 52 |
const url = new URL(request.url);
|
|
|
|
| 66 |
console.log("[getCurrentUser] Token verified, user_id:", payload.user_id);
|
| 67 |
|
| 68 |
// Fetch full user from database
|
| 69 |
+
// TODO: After Turso migration, re-add syncStatus, lastSyncAt, syncError to this select
|
| 70 |
const userRecords = await db
|
| 71 |
+
.select({
|
| 72 |
+
id: users.id,
|
| 73 |
+
githubId: users.githubId,
|
| 74 |
+
username: users.username,
|
| 75 |
+
avatarUrl: users.avatarUrl,
|
| 76 |
+
role: users.role,
|
| 77 |
+
githubAccessToken: users.githubAccessToken,
|
| 78 |
+
createdAt: users.createdAt,
|
| 79 |
+
updatedAt: users.updatedAt,
|
| 80 |
+
})
|
| 81 |
.from(users)
|
| 82 |
.where(eq(users.id, payload.user_id))
|
| 83 |
.limit(1);
|