From d50bf7c71d3cee294dafbe42f40b8b7dbe738c8a Mon Sep 17 00:00:00 2001 From: Mike Eling Date: Sat, 23 Dec 2023 04:14:57 +0100 Subject: [PATCH] :sparkles: Implement tasks.markDone method --- .env.example | 3 ++- bun.lockb | Bin 14751 -> 15100 bytes example/index.ts | 44 ++++++++++++++++-------------------- src/client.ts | 17 +++++++++++++- src/config.ts | 4 +++- src/modules/tasks.ts | 10 ++++++++ src/types.ts | 1 + src/utils.ts | 2 +- tests/mocks.ts | 6 ++++- tests/modules/tasks.test.ts | 11 ++++++--- 10 files changed, 65 insertions(+), 33 deletions(-) diff --git a/.env.example b/.env.example index 0cb8c4f..43a6449 100644 --- a/.env.example +++ b/.env.example @@ -1 +1,2 @@ -RECLAIM_ACCESS_TOKEN=xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx \ No newline at end of file +RECLAIM_ACCESS_TOKEN=xxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx +RECLAIM_VERBOSE=false \ No newline at end of file diff --git a/bun.lockb b/bun.lockb index afe1942eb039ad3610d9206330e84424b7b86bc6..c1fbed1f702efaddd4ab324d47017a6cac93fe38 100644 GIT binary patch delta 3020 zcmb_eeQZ-z6o2=%W$R|wjdfeQ0{algx~|>I7#$x{BuLN(CW%@%WdxW&aj+p^21r`t zREUxwM-vH%#Hcu;iHIbch#J%c{6G^heu73xw8C&`q6j+t{od=tkKjMVo1Ayv@0@$j zJ?Ff8&pS`9`hCroaNwS*2WI{N{54t!Z~9m*2Huv8FBQ>Rw1~q0+Q`=$9u~BzqRDT6HI| z6LWpqMZWaFxhL5 zI$z8p2a!50{lj9;ImpW`m|>H%j;Ql#psA)2M^t?y$()!YgbYoW7wnVOTFKz zjUur5BM^7UK^#$M5ZSr3pIRcB+?d)g0cTA8EJ-}0(vRmF$v9)qqsSQdvKuRlkT9Yg zSqVG6K;wXP2IJiG7lMyp0?jmaKn?hK(}4{C9V>xaWWYID^-Cr{rUoT&)#Mby)<_)W zIBOaLH3$ndoH3piWBi?S9uAo?ABWHwaz-R8V+Uge{rh+m&{>* zV_ZS%{+G<9t~_;DnzbgCWqSHQ6}NngtQEI$pBEkOdOt&?}45e9#<~O z06kvplG(*^<(6&537O?_$sa&Pa=j-Z=YU@D#8t8U2J~EsOXiitRf+VMB;?jom$*vf zs!ZBS6Ovozk^?|Kah4_I6`Tpbfsb zs*=M%z2zrTHp3R|)=HS<=1o6vR*PWQR zh&QVUL>-S4G3CV|%En|lFHA}Hoi~(oSZYRqxF!JNe3lISmb5x9r~^@m;;DH-lm$VQ zRc7z=N40Xk=7tnPGHyPDppW>+7^RD4j5BGU=2(`7gFGOXFkX6^r0=6aeo!@t)rJ*` zRfzF19{SJnMW0#DSlZ|-Tq`pKR8nE=2KI6QzSX1{FY~}S={jSlZTiO0m#y!M8W`?D*vUqq=HG>JZ(f&S=%J zEgKd+KB-q%mNlz4YJ201W5vt{i>Mw0w69CT4ThE$;<=eyfd}({S)9-@9*lpr2s6uw5=1 zh7i2}GLB3z9oa3jp}&kf6T{=e=wOWGsROdT-iLN=e|?i`l}!EY(bc#VOif-UF*3I6 z;q%zH2^JB+p|E+*avP*QG(&cU8p}^&GWwEqUrY1*s<&XMrNNxiIZ1v9wQe2fFE@{C YL#V-g2}LI0L`K4^m#o`2F}yhcPk-nGGXMYp delta 2776 zcmcImYitx%6rMZXZM&t@?Q7eeZcBkex4Uf@+Oo7uA8Vl@zy@fHx|E2@tG2PVrG-Ex z&^3Vs5;f{kV@+)dYD5A7tcfki+caPxg8mSBD8^ubQUb=<2QR-fvr{y|e>%yTGvB%Q zp8K71&%JZ+t?h1o)8l$q488LE+~xb@%10&VQ&&GWHQmeEad+YDQ)iAWT9pH?}ORm82INnwGQmB4ixwjrA|rH!o{#ogpO20^AEb>zlw< z=t^0V;-L42?H7RKfzLoI(ESm5{|@LF;MFGRc6`*r5DP7vB`Fnp2n{@;JFEv_X9qJQ z^?{Fdgm%M^F}@{ACuI2P1~Dc?(YpVw(BpZcb#?VC>d;ug49kQUn% zIs}wNmXshxrzq5z5)d}(1L_6JNDYWos!t74U8+K7fK*cLL9*Kw+Gr052b}^s36!q} zL`b~HYM`l^DkVH#dC$8B9B*+da2u; z>pg~cOcc5Z%|FmB@y|9iY!;p9SKuj_<|&YjOTz81H#T?vaQb^0CHv5=W*H-mOGC|( zTjtK626MC-c%W2CrMYUlacSt<_4YuD?Yk{#FY!$C;IDH*rsiC`*ZA4rZxH*MCskcQ z2d}4qJ8VO)x!i|GH`E { - console.log("Create a task =>"); + console.log("\n\nCreate a task =>\n"); const newTask = await client.tasks.create({ - "title": "Test", + "title": "Funky Imitation Game", "eventColor": null, "eventCategory": "WORK", "timeChunksRequired": 4, @@ -21,74 +21,67 @@ const createTaskExample = async () => { "onDeck": false }); - console.log(newTask, "\n\n"); - return newTask; } const searchTasksExample = async () => { - console.log("Search tasks =>"); - - const tasks = await client.tasks.search({title: "Test"}); + console.log("\n\nSearch tasks =>\n"); - console.log(tasks, "\n\n"); + const tasks = await client.tasks.search({title: "Funky Imitation Game"}); return tasks; } const updateTaskExample = async (taskId: number) => { - console.log("Update a task =>"); + console.log("\n\nUpdate a task =>\n"); const updatedTask = await client.tasks.update(taskId, { - "title": "Test 2", + "title": "Indistinguishable Turing Test", }); - console.log(updatedTask, "\n\n"); - return updatedTask; } const getTaskExample = async (taskId: number) => { - console.log("Get a task =>"); + console.log("\n\nGet a task =>\n"); const task = await client.tasks.get(taskId); - console.log(task, "\n\n"); - return task; } const deleteTaskExample = async (taskId: number) => { - console.log("Delete a task =>"); + console.log("\n\nDelete a task =>\n"); const deletedTask = await client.tasks.delete(taskId); - console.log(deletedTask, "\n\n"); - return deletedTask; } const getCurrentUserExample = async () => { - console.log("Get current user =>"); + console.log("\n\nGet current user =>\n"); const user = await client.users.current(); - console.log(user, "\n\n"); - return user; } const updateCurrentUserExample = async () => { - console.log("Update current user =>"); + console.log("\n\nUpdate current user =>\n"); const updatedUser = await client.users.update({ companyName: "Assembless" }); - console.log(updatedUser, "\n\n"); - console.log(updatedUser.metadata.companyName) - return updatedUser; } +const markTaskAsDoneExample = async (taskId: number) => { + console.log("\n\nMark task as done =>\n"); + + const doneTask = await client.tasks.markDone(taskId); + + return doneTask; +} + // This is an example of how to use the ReclaimClient class. const main = async () => { console.clear(); @@ -102,6 +95,7 @@ const main = async () => { await searchTasksExample(); await updateTaskExample(taskId); await getTaskExample(taskId); + await markTaskAsDoneExample(taskId); await deleteTaskExample(taskId); } diff --git a/src/client.ts b/src/client.ts index d19ee22..c8b2c2b 100644 --- a/src/client.ts +++ b/src/client.ts @@ -40,7 +40,7 @@ export class ReclaimClient { /** * @description A generic fetcher for the Reclaim API. * @param endpoint - * @param options + * @param options */ async _fetcher(endpoint: string, options: RequestInit) { const opts = { @@ -56,10 +56,25 @@ export class ReclaimClient { `${config.reclaim.apiUrl}/api/${endpoint}`, opts ); + + this.verbose( + `[${endpoint}] (${response.status})`, + `Response from Reclaim API`, + response + ); + return await response.json(); } catch (err) { console.error(err); throw new Error("Error fetching data from Reclaim API."); } } + + /** + * @description A verbose logger. + * @param args + */ + verbose(...args: any[]) { + if (config.verbose) console.log(...args); + } } diff --git a/src/config.ts b/src/config.ts index faafeae..3ec2f16 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,6 +1,7 @@ const RECLAIM_API_URL = "https://api.app.reclaim.ai"; const RECLAIM_ACCESS_TOKEN = process?.env?.RECLAIM_ACCESS_TOKEN; +const RECLAIM_VERBOSE = process?.env?.RECLAIM_VERBOSE === "true"; /** * @description Configuration for the Reclaim API client. @@ -9,5 +10,6 @@ export const config = Object.freeze({ reclaim: { apiUrl: RECLAIM_API_URL, accessToken: RECLAIM_ACCESS_TOKEN - } + }, + verbose: RECLAIM_VERBOSE }); \ No newline at end of file diff --git a/src/modules/tasks.ts b/src/modules/tasks.ts index 88045c6..1141f73 100644 --- a/src/modules/tasks.ts +++ b/src/modules/tasks.ts @@ -79,4 +79,14 @@ export class ReclaimTasks { method: "DELETE", }); } + + /** + * @description Mark a task as done. + * @param id The ID of the task to mark as done. + */ + async markDone(id: number): Promise<{ taskOrHabit: ReclaimTask, events: unknown[] }> { + return await this.client._fetcher(`${ReclaimEndpoints.Planner}/done/task/${id}`, { + method: "POST", + }); + } } diff --git a/src/types.ts b/src/types.ts index cf33c15..0d3c6dd 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,5 +1,6 @@ export enum ReclaimEndpoints { Tasks = "tasks", + Planner = "planner", Users = "users", Calendars = "calendars", } diff --git a/src/utils.ts b/src/utils.ts index 9e176b5..8571c93 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -14,4 +14,4 @@ export function filterArray(array: T[], filters: Partial): T[] { return item[key] === filters[key]; }); }); -} +} \ No newline at end of file diff --git a/tests/mocks.ts b/tests/mocks.ts index 04d8efc..926842a 100644 --- a/tests/mocks.ts +++ b/tests/mocks.ts @@ -1,7 +1,7 @@ import { ReclaimTaskCreate } from "../src/types"; export const ReclaimTaskCreateMock: ReclaimTaskCreate = Object.freeze({ - title: "Test Task 1", + title: "Funky Imitation Game", eventColor: null, eventCategory: "WORK", timeChunksRequired: 8, @@ -14,3 +14,7 @@ export const ReclaimTaskCreateMock: ReclaimTaskCreate = Object.freeze({ due: "2029-11-21T16:30:00.000Z", onDeck: false, }); + +export const ReclaimTaskUpdateMock: Partial = Object.freeze({ + title: "Indistinguishable Turing Test", +}); \ No newline at end of file diff --git a/tests/modules/tasks.test.ts b/tests/modules/tasks.test.ts index 7877ab0..e874f13 100644 --- a/tests/modules/tasks.test.ts +++ b/tests/modules/tasks.test.ts @@ -1,7 +1,7 @@ import { beforeEach, describe, expect, test } from "bun:test"; import { ReclaimClient } from "../../src"; import { ReclaimTasks } from "../../src/modules/tasks"; -import { ReclaimTaskCreateMock } from "../mocks"; +import { ReclaimTaskCreateMock, ReclaimTaskUpdateMock } from "../mocks"; describe("ReclaimTasks", () => { let tasks: ReclaimTasks; @@ -37,15 +37,20 @@ describe("ReclaimTasks", () => { expect(filterResults[0].title).toBe(ReclaimTaskCreateMock.title); // Test task update - const updateResults = await tasks.update(createResults.id, { title: "Updated Test Task 1" }); + const updateResults = await tasks.update(createResults.id, ReclaimTaskUpdateMock); expect(updateResults).toBeTruthy(); expect(updateResults.id).toBe(updateResults.id); - expect(updateResults.title).toBe("Updated Test Task 1"); + expect(updateResults.title).toBe(ReclaimTaskUpdateMock.title); // Test task get const getResults = await tasks.get(createResults.id); expect(getResults).toBeTruthy(); expect(getResults.id).toBe(createResults.id); + + // Test task mark as done + const markAsDoneResults = await tasks.markDone(createResults.id); + expect(markAsDoneResults).toBeTruthy(); + expect(markAsDoneResults.taskOrHabit.id).toBe(createResults.id); // Test task delete const deleteResults = await tasks.delete(createResults.id);