199 lines
5.5 KiB
TypeScript
199 lines
5.5 KiB
TypeScript
"use client";
|
|
|
|
import { createNotesApiClient } from "@/lib/api-helpers";
|
|
import { RETRY_WHEN_ONLINE_MESSAGE, withMutationRetry } from "@/lib/mutation-retry";
|
|
|
|
// ── Types ────────────────────────────────────────────────────────
|
|
|
|
export type IntakeContentType =
|
|
| "youtube"
|
|
| "article"
|
|
| "pdf"
|
|
| "tweet"
|
|
| "reddit"
|
|
| "github"
|
|
| "generic";
|
|
|
|
export type IntakeJobStatus =
|
|
| "queued"
|
|
| "extracting"
|
|
| "processing"
|
|
| "complete"
|
|
| "failed";
|
|
|
|
export interface IntakeSubmitResult {
|
|
jobId: string;
|
|
noteId: string;
|
|
contentType: IntakeContentType;
|
|
ruleMatched: string | null;
|
|
templateSlug: string;
|
|
status: "queued";
|
|
}
|
|
|
|
export interface IntakeJob {
|
|
id: string;
|
|
noteId: string;
|
|
url: string;
|
|
contentType: IntakeContentType;
|
|
templateSlug: string;
|
|
status: IntakeJobStatus;
|
|
error?: string;
|
|
startedAt: string;
|
|
completedAt?: string;
|
|
}
|
|
|
|
export interface IntakeRule {
|
|
id: string;
|
|
userId: string;
|
|
name: string;
|
|
urlPattern: string;
|
|
contentType: IntakeContentType;
|
|
templateId: string;
|
|
enabled: boolean;
|
|
priority: number;
|
|
}
|
|
|
|
// ── API Calls ────────────────────────────────────────────────────
|
|
|
|
export async function submitIntake(
|
|
url: string,
|
|
workspaceId?: string,
|
|
templateOverride?: string,
|
|
): Promise<IntakeSubmitResult> {
|
|
const api = createNotesApiClient();
|
|
const payload: Record<string, string> = { url };
|
|
if (workspaceId) payload.workspaceId = workspaceId;
|
|
if (templateOverride) payload.templateOverride = templateOverride;
|
|
return withMutationRetry({
|
|
run: () => api.fetch("/intake", {
|
|
method: "POST",
|
|
body: JSON.stringify(payload),
|
|
}),
|
|
offlineMessage: RETRY_WHEN_ONLINE_MESSAGE,
|
|
});
|
|
}
|
|
|
|
export async function listIntakeJobs(options?: {
|
|
status?: IntakeJobStatus;
|
|
limit?: number;
|
|
}): Promise<{ items: IntakeJob[]; total: number }> {
|
|
const api = createNotesApiClient();
|
|
const params = new URLSearchParams();
|
|
if (options?.status) params.set("status", options.status);
|
|
if (options?.limit) params.set("limit", String(options.limit));
|
|
const qs = params.toString();
|
|
return api.fetch(`/intake/jobs${qs ? `?${qs}` : ""}`);
|
|
}
|
|
|
|
export async function getIntakeJob(id: string): Promise<IntakeJob> {
|
|
const api = createNotesApiClient();
|
|
return api.fetch(`/intake/jobs/${encodeURIComponent(id)}`);
|
|
}
|
|
|
|
export async function listIntakeRules(): Promise<{
|
|
items: IntakeRule[];
|
|
total: number;
|
|
}> {
|
|
const api = createNotesApiClient();
|
|
return api.fetch("/intake-rules");
|
|
}
|
|
|
|
export async function createIntakeRule(
|
|
rule: Omit<IntakeRule, "id" | "userId">,
|
|
): Promise<IntakeRule> {
|
|
const api = createNotesApiClient();
|
|
return withMutationRetry({
|
|
run: () => api.fetch("/intake-rules", {
|
|
method: "POST",
|
|
body: JSON.stringify(rule),
|
|
}),
|
|
queue: { id: rule.name, action: "post", path: "/intake-rules", payload: rule },
|
|
});
|
|
}
|
|
|
|
export async function deleteIntakeRule(id: string): Promise<void> {
|
|
const api = createNotesApiClient();
|
|
const path = `/intake-rules/${encodeURIComponent(id)}`;
|
|
await withMutationRetry({
|
|
run: () => api.fetch(path, {
|
|
method: "DELETE",
|
|
}),
|
|
queue: { id, action: "delete", path, payload: {} },
|
|
});
|
|
}
|
|
|
|
// ── Sharing helpers ──────────────────────────────────────────────
|
|
|
|
export async function shareNoteWithUser(
|
|
noteId: string,
|
|
workspaceId: string,
|
|
sharedWithUserId: string,
|
|
permission: "view" | "comment" | "edit" = "view",
|
|
): Promise<unknown> {
|
|
const api = createNotesApiClient();
|
|
const path = `/notes/${encodeURIComponent(noteId)}/share-with-user`;
|
|
return withMutationRetry({
|
|
run: () => api.fetch(path, {
|
|
method: "POST",
|
|
body: JSON.stringify({ workspaceId, sharedWithUserId, permission }),
|
|
}),
|
|
offlineMessage: RETRY_WHEN_ONLINE_MESSAGE,
|
|
});
|
|
}
|
|
|
|
export async function listCollaborators(
|
|
noteId: string,
|
|
workspaceId: string,
|
|
): Promise<{ items: unknown[]; total: number }> {
|
|
const api = createNotesApiClient();
|
|
return api.fetch(`/notes/${encodeURIComponent(noteId)}/collaborators?workspaceId=${encodeURIComponent(workspaceId)}`);
|
|
}
|
|
|
|
export async function listSharedWithMe(): Promise<{
|
|
items: unknown[];
|
|
total: number;
|
|
}> {
|
|
const api = createNotesApiClient();
|
|
return api.fetch("/shared-with-me");
|
|
}
|
|
|
|
export async function removeCollaborator(
|
|
noteId: string,
|
|
userId: string,
|
|
): Promise<void> {
|
|
const api = createNotesApiClient();
|
|
const path = `/notes/${encodeURIComponent(noteId)}/collaborators/${encodeURIComponent(userId)}`;
|
|
await withMutationRetry({
|
|
run: () => api.fetch(path, {
|
|
method: "DELETE",
|
|
}),
|
|
offlineMessage: RETRY_WHEN_ONLINE_MESSAGE,
|
|
});
|
|
}
|
|
|
|
export async function exportNoteText(
|
|
noteId: string,
|
|
workspaceId: string,
|
|
): Promise<{
|
|
title: string;
|
|
markdown: string;
|
|
plaintext: string;
|
|
html: string;
|
|
}> {
|
|
const api = createNotesApiClient();
|
|
return api.fetch(`/notes/${encodeURIComponent(noteId)}/export-text`, {
|
|
method: "POST",
|
|
body: JSON.stringify({ workspaceId }),
|
|
});
|
|
}
|
|
|
|
export async function getNoteDeepLinks(
|
|
noteId: string,
|
|
workspaceId: string,
|
|
): Promise<{ web: string; mobile: string; public: string | null }> {
|
|
const api = createNotesApiClient();
|
|
return api.fetch(
|
|
`/notes/${encodeURIComponent(noteId)}/deep-link?workspaceId=${encodeURIComponent(workspaceId)}`,
|
|
);
|
|
}
|