refactor(web): extract shared API client factory, fix types, use crypto.randomUUID
- Created api-helpers.ts with shared getAccessToken() + createNotesApiClient() - Removed duplicate API client factory from notes-client.ts, review-client.ts, saved-views-client.ts (3 copies → 1 shared module) - Added reviewedBy/reviewedAt/reviewNote fields to review-client NoteAgentActionDoc type to match backend response shape - Search page: use crypto.randomUUID() for saved view IDs instead of Date.now() to prevent collisions on rapid saves Verification: web typecheck + 6/6 tests pass.
This commit is contained in:
parent
c6aa775cd3
commit
c2202e9e52
@ -46,7 +46,7 @@ export default function SearchPage() {
|
||||
if (!query.trim()) return;
|
||||
try {
|
||||
const view = await createSavedView({
|
||||
id: `sv-${Date.now()}`,
|
||||
id: crypto.randomUUID(),
|
||||
name: query.trim().slice(0, 60),
|
||||
scope: "search",
|
||||
query: query.trim(),
|
||||
|
||||
20
web/src/lib/api-helpers.ts
Normal file
20
web/src/lib/api-helpers.ts
Normal file
@ -0,0 +1,20 @@
|
||||
import { createApiClient } from "@bytelyst/api-client";
|
||||
import { NOTES_API_URL, PRODUCT_ID } from "@/lib/product-config";
|
||||
|
||||
export function getAccessToken(): string | null {
|
||||
if (typeof window === "undefined") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return localStorage.getItem(`${PRODUCT_ID}_access_token`);
|
||||
}
|
||||
|
||||
export function createNotesApiClient() {
|
||||
return createApiClient({
|
||||
baseUrl: NOTES_API_URL,
|
||||
getToken: getAccessToken,
|
||||
defaultHeaders: {
|
||||
"x-product-id": PRODUCT_ID,
|
||||
},
|
||||
});
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
import { createApiClient } from "@bytelyst/api-client";
|
||||
import { extractSuggestedTasks } from "@/lib/extraction-client";
|
||||
import { NOTES_API_URL, PRODUCT_ID } from "@/lib/product-config";
|
||||
import { PRODUCT_ID } from "@/lib/product-config";
|
||||
import { createNotesApiClient } from "@/lib/api-helpers";
|
||||
import type { AgentTimelineItem, ArtifactSummary, LinkedNote, NoteDetail, NoteSummary, NoteTask, WorkspaceSummary } from "@/lib/types";
|
||||
|
||||
type NoteDoc = {
|
||||
@ -90,23 +90,6 @@ type NoteRelationshipListResponse = {
|
||||
items: NoteRelationshipDoc[];
|
||||
};
|
||||
|
||||
function getAccessToken(): string | null {
|
||||
if (typeof window === "undefined") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return localStorage.getItem(`${PRODUCT_ID}_access_token`);
|
||||
}
|
||||
|
||||
function createNotesApiClient() {
|
||||
return createApiClient({
|
||||
baseUrl: NOTES_API_URL,
|
||||
getToken: getAccessToken,
|
||||
defaultHeaders: {
|
||||
"x-product-id": PRODUCT_ID,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function buildWorkspaceMap(workspaces: WorkspaceDoc[]) {
|
||||
return new Map(workspaces.map((workspace) => [workspace.id, workspace]));
|
||||
|
||||
@ -1,5 +1,4 @@
|
||||
import { createApiClient } from "@bytelyst/api-client";
|
||||
import { NOTES_API_URL, PRODUCT_ID } from "@/lib/product-config";
|
||||
import { createNotesApiClient } from "@/lib/api-helpers";
|
||||
import type { AgentTimelineItem, ApprovalQueueItem } from "@/lib/types";
|
||||
import { listWorkspaceSummaries } from "@/lib/notes-client";
|
||||
|
||||
@ -15,6 +14,9 @@ type NoteAgentActionDoc = {
|
||||
reason?: string;
|
||||
beforeSummary?: string;
|
||||
afterSummary?: string;
|
||||
reviewedBy?: string;
|
||||
reviewedAt?: string;
|
||||
reviewNote?: string;
|
||||
updatedAt: string;
|
||||
};
|
||||
|
||||
@ -22,23 +24,6 @@ type NoteAgentActionListResponse = {
|
||||
items: NoteAgentActionDoc[];
|
||||
};
|
||||
|
||||
function getAccessToken(): string | null {
|
||||
if (typeof window === "undefined") {
|
||||
return null;
|
||||
}
|
||||
|
||||
return localStorage.getItem(`${PRODUCT_ID}_access_token`);
|
||||
}
|
||||
|
||||
function createNotesApiClient() {
|
||||
return createApiClient({
|
||||
baseUrl: NOTES_API_URL,
|
||||
getToken: getAccessToken,
|
||||
defaultHeaders: {
|
||||
"x-product-id": PRODUCT_ID,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
function toSeverity(actionType: NoteAgentActionDoc["actionType"]): ApprovalQueueItem["severity"] {
|
||||
if (actionType === "update" || actionType === "extract_tasks") {
|
||||
|
||||
@ -1,7 +1,6 @@
|
||||
"use client";
|
||||
|
||||
import { createApiClient } from "@bytelyst/api-client";
|
||||
import { NOTES_API_URL, PRODUCT_ID } from "@/lib/product-config";
|
||||
import { createNotesApiClient } from "@/lib/api-helpers";
|
||||
|
||||
export interface SavedView {
|
||||
id: string;
|
||||
@ -20,19 +19,6 @@ interface SavedViewListResponse {
|
||||
total: number;
|
||||
}
|
||||
|
||||
function getAccessToken(): string | null {
|
||||
if (typeof window === "undefined") return null;
|
||||
return localStorage.getItem(`${PRODUCT_ID}_access_token`);
|
||||
}
|
||||
|
||||
function createNotesApiClient() {
|
||||
return createApiClient({
|
||||
baseUrl: NOTES_API_URL,
|
||||
getToken: getAccessToken,
|
||||
defaultHeaders: { "x-product-id": PRODUCT_ID },
|
||||
});
|
||||
}
|
||||
|
||||
export async function listSavedViews(scope?: SavedView["scope"]): Promise<SavedView[]> {
|
||||
const api = createNotesApiClient();
|
||||
const params = new URLSearchParams();
|
||||
|
||||
Loading…
Reference in New Issue
Block a user