@swoft/gtd-domain
Version:
Getting Things Done (GTD) productivity system - consolidated domain implementation
262 lines (260 loc) • 8.57 kB
JavaScript
import {
ApiValidationError,
BackendApiError,
BackendInboxListResponseSchema,
classifyError,
defaultErrorLogger,
isBackendSuccessResponse,
withRetry
} from "./chunk-GQ5XH56W.mjs";
import {
__name
} from "./chunk-PAWJFY3S.mjs";
// src/client/gtd-client.ts
var GTDClient = class {
static {
__name(this, "GTDClient");
}
http;
basePath;
config;
constructor(http, basePath = "/api/productivity/gtd", config = {}) {
this.http = http;
this.basePath = basePath;
this.config = {
enableValidation: true,
enableRetry: true,
errorLogger: defaultErrorLogger,
...config
};
}
async executeRequest(operation) {
try {
if (this.config.enableRetry) {
return await withRetry(operation);
}
return await operation();
} catch (error) {
const standardError = classifyError(error);
this.config.errorLogger?.logError(standardError);
throw standardError;
}
}
validateResponse(data, schema, operationName) {
if (!this.config.enableValidation) {
return data;
}
const result = schema.safeParse(data);
if (!result.success) {
throw new ApiValidationError(`Invalid response format for ${operationName}`, result.error.issues);
}
return result.data;
}
// Inbox Operations
async getInboxItems(filters) {
return this.executeRequest(async () => {
const queryParams = filters ? new URLSearchParams(Object.entries(filters).filter(([_, value]) => value !== void 0).reduce((acc, [key, value]) => ({
...acc,
[key]: String(value)
}), {})).toString() : "";
const url = queryParams ? `${this.basePath}/inbox?${queryParams}` : `${this.basePath}/inbox`;
const rawResponse = await this.http.get(url, {
headers: {
"Content-Type": "application/json"
}
});
const validatedResponse = this.validateResponse(rawResponse, BackendInboxListResponseSchema, "getInboxItems");
if (!isBackendSuccessResponse(validatedResponse)) {
throw BackendApiError.fromBackendError(validatedResponse);
}
const { data } = validatedResponse;
return {
items: data.items.map((item) => ({
id: item.id,
originalContent: item.content || item.text || item.title || "",
capturedAt: item.capturedAt,
capturedByPersonId: item.capturedBy || "unknown",
processingStatus: item.status === "processed" ? "processed" : "unprocessed",
clarification: item.clarification || void 0,
isActionable: item.isActionable || void 0,
// These fields are not available in backend response yet - use undefined for now
lastRefinedAt: void 0,
refinedByPersonId: void 0
})),
pagination: {
totalCount: data.total
},
totalCount: data.total
};
});
}
async getInboxItem(id) {
const response = await this.http.get(`${this.basePath}/inbox/${id}`);
return response.item || null;
}
async captureInboxItem(request) {
const response = await this.http.post(`${this.basePath}/inbox`, request);
return response.item || response;
}
async refineInboxItem(id, request) {
const response = await this.http.post(`${this.basePath}/inbox/${id}/refine`, request);
return response.item || response;
}
async clarifyInboxItem(id, request) {
const response = await this.http.post(`${this.basePath}/inbox/${id}/clarify`, request);
return response.item || response;
}
async processInboxItem(id, request) {
return this.http.post(`${this.basePath}/inbox/${id}/process`, request);
}
async deleteInboxItem(id) {
await this.http.delete(`${this.basePath}/inbox/${id}`);
}
// Project Operations
async getProjects(filters) {
const queryParams = filters ? new URLSearchParams(Object.entries(filters).filter(([_, value]) => value !== void 0).reduce((acc, [key, value]) => ({
...acc,
[key]: String(value)
}), {})).toString() : "";
const url = queryParams ? `${this.basePath}/projects?${queryParams}` : `${this.basePath}/projects`;
const response = await this.http.get(url);
if (response.items && response.total !== void 0) {
return {
items: response.items,
pagination: {
totalCount: response.total,
page: response.meta?.page,
pageSize: response.meta?.limit
},
totalCount: response.total
};
}
const items = Array.isArray(response) ? response : [];
return {
items,
pagination: {
totalCount: items.length
},
totalCount: items.length
};
}
async getProject(id) {
const response = await this.http.get(`${this.basePath}/projects/${id}`);
return response.item || null;
}
async createProject(request) {
const response = await this.http.post(`${this.basePath}/projects`, request);
return response.item || response;
}
async completeProject(id, completedBy, completionNotes) {
const response = await this.http.post(`${this.basePath}/projects/${id}/complete`, {
completedBy,
completionNotes
});
return response.item || response;
}
async deferProject(id) {
const response = await this.http.post(`${this.basePath}/projects/${id}/defer`);
return response.item || response;
}
async activateProject(id) {
const response = await this.http.post(`${this.basePath}/projects/${id}/activate`);
return response.item || response;
}
async cancelProject(id) {
const response = await this.http.post(`${this.basePath}/projects/${id}/cancel`);
return response.item || response;
}
async deleteProject(id) {
await this.http.delete(`${this.basePath}/projects/${id}`);
}
// Next Action Operations
async getNextActions(filters) {
const queryParams = filters ? new URLSearchParams(Object.entries(filters).filter(([_, value]) => value !== void 0).reduce((acc, [key, value]) => ({
...acc,
[key]: String(value)
}), {})).toString() : "";
const url = queryParams ? `${this.basePath}/actions?${queryParams}` : `${this.basePath}/actions`;
const response = await this.http.get(url);
if (response.items && response.total !== void 0) {
return {
items: response.items,
pagination: {
totalCount: response.total,
page: response.meta?.page,
pageSize: response.meta?.limit
},
totalCount: response.total
};
}
const items = Array.isArray(response) ? response : [];
return {
items,
pagination: {
totalCount: items.length
},
totalCount: items.length
};
}
async getNextAction(id) {
const response = await this.http.get(`${this.basePath}/actions/${id}`);
return response.item || null;
}
async createNextAction(request) {
const response = await this.http.post(`${this.basePath}/actions`, request);
return response.item || response;
}
async assignNextAction(id, request) {
const response = await this.http.post(`${this.basePath}/actions/${id}/assign`, request);
return response.item || response;
}
async unassignNextAction(id) {
const response = await this.http.post(`${this.basePath}/actions/${id}/unassign`);
return response.item || response;
}
async completeNextAction(id) {
const response = await this.http.post(`${this.basePath}/actions/${id}/complete`);
return response.item || response;
}
async deleteNextAction(id) {
await this.http.delete(`${this.basePath}/actions/${id}`);
}
// Convenience methods that match the existing frontend API
async getActionsByProject(projectId) {
return this.getNextActions({
projectId
});
}
async getActionsByContext(context) {
return this.getNextActions({
context
});
}
async getContexts() {
const response = await this.http.get(`${this.basePath}/contexts`);
const contexts = Array.isArray(response) ? response : [];
return {
items: contexts,
pagination: {
totalCount: contexts.length
},
totalCount: contexts.length
};
}
// Weekly Review
async getWeeklyReview(reviewedBy) {
const queryParams = new URLSearchParams({
reviewedBy
}).toString();
const response = await this.http.get(`${this.basePath}/weekly-review?${queryParams}`, {
headers: {
"Content-Type": "application/json"
}
});
return response.review || response;
}
};
export {
GTDClient
};
//# sourceMappingURL=chunk-KWIF3JSN.mjs.map