From 0784201af539dab4da025a861b9a5d2c0dd5db2a Mon Sep 17 00:00:00 2001 From: QuantCode Agent Date: Thu, 12 Nov 2026 04:07:42 +0000 Subject: [PATCH] docs: add JSDoc comments to exported functions in src/ --- src/calculator.ts | 31 +++++++++++++++++++++++++++ src/date-utils.ts | 15 ++++++++++++- src/string-utils.ts | 36 +++++++++++++++++++++++++++++++ src/task-manager.ts | 52 +++++++++++++++++++++++++++++++++++++++++++++ src/validator.ts | 16 ++++++++++++++ 5 files changed, 149 insertions(+), 1 deletion(-) diff --git a/src/calculator.ts b/src/calculator.ts index 68b894d..9bacdaa 100644 --- a/src/calculator.ts +++ b/src/calculator.ts @@ -3,19 +3,50 @@ * Used for testing QuantCode autonomous agent capabilities. */ +/** + * Add two numbers. + * + * @param a - The first addend. + * @param b - The second addend. + * @returns The sum of `a` and `b`. + */ export function add(a: number, b: number): number { return a + b } +/** + * Subtract one number from another. + * + * @param a - The minuend. + * @param b - The subtrahend. + * @returns The difference `a - b`. + */ export function subtract(a: number, b: number): number { return a - b } +/** + * Multiply two numbers. + * + * @param a - The first factor. + * @param b - The second factor. + * @returns The product of `a` and `b`. + */ export function multiply(a: number, b: number): number { return a * b } // BUG: Division by zero is not handled +/** + * Divide one number by another. + * + * Division by zero is not guarded: it follows IEEE 754 and returns + * `Infinity`, `-Infinity` or `NaN` rather than throwing. + * + * @param a - The dividend. + * @param b - The divisor. + * @returns The quotient `a / b`. + */ export function divide(a: number, b: number): number { return a / b } diff --git a/src/date-utils.ts b/src/date-utils.ts index 37272a7..57af6f9 100644 --- a/src/date-utils.ts +++ b/src/date-utils.ts @@ -8,6 +8,11 @@ * * BUG: off-by-one — uses Math.floor where Math.round is needed for days, * causing "1 day ago" to appear for anything from 12h to 47h. + * + * @param date - The date to describe. + * @param now - The reference point to compare against. Defaults to the current time. + * @returns "just now" within a minute, otherwise a minutes, hours or days string, + * suffixed "ago" for past dates or prefixed "in" for future dates. */ export function formatRelative(date: Date, now: Date = new Date()): string { const diffMs = now.getTime() - date.getTime() @@ -30,7 +35,11 @@ export function formatRelative(date: Date, now: Date = new Date()): string { } /** - * Returns true if two dates fall on the same calendar day. + * Returns true if two dates fall on the same calendar day (local time). + * + * @param a - The first date. + * @param b - The second date. + * @returns `true` if both dates share the same year, month and day, otherwise `false`. */ export function isSameDay(a: Date, b: Date): boolean { return a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate() @@ -38,6 +47,10 @@ export function isSameDay(a: Date, b: Date): boolean { /** * Add a number of days to a date (returns a new Date). + * + * @param date - The starting date; it is not mutated. + * @param days - The number of days to add; negative values subtract. + * @returns A new Date offset by the given number of days. */ export function addDays(date: Date, days: number): Date { const result = new Date(date) diff --git a/src/string-utils.ts b/src/string-utils.ts index 63fba18..e0b2e8b 100644 --- a/src/string-utils.ts +++ b/src/string-utils.ts @@ -2,21 +2,50 @@ * String utility functions. */ +/** + * Upper-case the first character of a string, leaving the rest unchanged. + * + * @param str - The string to capitalise. + * @returns The string with its first character upper-cased, or `str` itself if it is empty. + */ export function capitalize(str: string): string { if (!str) return str return str.charAt(0).toUpperCase() + str.slice(1) } +/** + * Reverse the characters of a string (by UTF-16 code unit). + * + * @param str - The string to reverse. + * @returns A new string with the characters in reverse order. + */ export function reverse(str: string): string { return str.split("").reverse().join("") } // TODO: implement truncate — should truncate at a word boundary, with "..." // counting toward maxLength. Return unchanged if str.length <= maxLength. +/** + * Truncate a string to a maximum length. Not yet implemented. + * + * @param str - The string to truncate. + * @param maxLength - The maximum permitted length of the result. + * @returns The truncated string. + * @throws {Error} Always, with message "not implemented", until implemented. + */ export function truncate(str: string, maxLength: number): string { throw new Error("not implemented") } +/** + * Convert a string to a URL-friendly slug: lower-cased, with each run of + * characters other than ASCII letters and digits (a-z, 0-9) replaced by a single + * hyphen and leading or trailing hyphens removed. Non-ASCII characters, including + * accented letters such as "é", are treated as separators and are not preserved. + * + * @param str - The string to convert. + * @returns The slugified string. + */ export function slugify(str: string): string { return str .toLowerCase() @@ -25,6 +54,13 @@ export function slugify(str: string): string { } // BUG: This doesn't handle multiple consecutive spaces +/** + * Count the words in a string, splitting on single space characters. + * Consecutive spaces are not collapsed and so can inflate the count. + * + * @param str - The string to count words in. + * @returns The number of words, or 0 if the string is empty or whitespace only. + */ export function wordCount(str: string): number { if (!str.trim()) return 0 return str.split(" ").length diff --git a/src/task-manager.ts b/src/task-manager.ts index a920e85..02d62ae 100644 --- a/src/task-manager.ts +++ b/src/task-manager.ts @@ -16,10 +16,21 @@ export interface Task { completedAt?: Date } +/** + * In-memory task manager that stores tasks with priorities and status tracking. + */ export class TaskManager { private tasks: Map = new Map() private nextId = 1 + /** + * Create a new task with status `pending` and store it. + * + * @param title - The task title. + * @param priority - The task priority. Defaults to `"medium"`. + * @param description - Optional longer description of the task. + * @returns The newly created task. + */ add(title: string, priority: Priority = "medium", description?: string): Task { const task: Task = { id: String(this.nextId++), @@ -33,10 +44,22 @@ export class TaskManager { return task } + /** + * Look up a task by id. + * + * @param id - The task id. + * @returns The matching task, or `undefined` if none exists. + */ get(id: string): Task | undefined { return this.tasks.get(id) } + /** + * List tasks, optionally filtered by status and/or priority. + * + * @param filter - Optional filter; when both fields are set a task must match both. + * @returns The matching tasks in insertion order. + */ list(filter?: { status?: Status; priority?: Priority }): Task[] { let result = Array.from(this.tasks.values()) if (filter?.status) result = result.filter((t) => t.status === filter.status) @@ -44,6 +67,12 @@ export class TaskManager { return result } + /** + * Mark a task as completed and record its completion time. + * + * @param id - The id of the task to complete. + * @returns `true` if the task was found and completed, `false` if not found. + */ complete(id: string): boolean { const task = this.tasks.get(id) if (!task) return false @@ -53,18 +82,41 @@ export class TaskManager { } // TODO: implement — remove a task by id, return true if removed, false if not found + /** + * Remove a task by id. Not yet implemented. + * + * @param id - The id of the task to remove. + * @returns `true` if a task was removed, `false` if not found (once implemented). + * @throws {Error} Always, with message "not implemented", until implemented. + */ remove(id: string): boolean { throw new Error("not implemented") } // TODO: implement — update title/description/priority of a task // return true if updated, false if not found + /** + * Update the title, description and/or priority of a task. Not yet implemented. + * + * @param id - The id of the task to update. + * @param changes - The fields to change. + * @returns `true` if the task was updated, `false` if not found (once implemented). + * @throws {Error} Always, with message "not implemented", until implemented. + */ update(id: string, changes: Partial>): boolean { throw new Error("not implemented") } // TODO: implement — return all tasks sorted by the given field // priority sort order: high > medium > low + /** + * Return all tasks sorted by the given field, with priority ordered high > medium > low. + * Not yet implemented. + * + * @param field - The field to sort by. + * @returns The sorted tasks (once implemented). + * @throws {Error} Always, with message "not implemented", until implemented. + */ sortBy(field: "priority" | "createdAt" | "status"): Task[] { throw new Error("not implemented") } diff --git a/src/validator.ts b/src/validator.ts index 27bf385..7fc2d1c 100644 --- a/src/validator.ts +++ b/src/validator.ts @@ -7,6 +7,9 @@ * * BUG: the regex does not allow subdomains (e.g. user@mail.example.com fails) * and rejects valid TLDs longer than 4 chars (e.g. .museum, .travel). + * + * @param value - The string to test. + * @returns `true` if the string matches the email pattern, otherwise `false`. */ export function isEmail(value: string): boolean { // BUG: too restrictive — missing subdomain support and long TLDs @@ -17,6 +20,11 @@ export function isEmail(value: string): boolean { * Returns true if the string is a valid URL (http or https). * * BUG: rejects URLs with ports (e.g. http://localhost:3000) + * + * @param value - The string to test. + * @returns `true` if the string parses as an http(s) URL with no port other than the + * protocol's default (the URL parser drops default ports, so `http://x.com:80` passes), + * otherwise `false`. Unparseable input returns `false` rather than throwing. */ export function isUrl(value: string): boolean { try { @@ -31,6 +39,11 @@ export function isUrl(value: string): boolean { /** * Returns true if the string contains only alphanumeric characters and underscores, * starts with a letter, and is between minLen and maxLen characters. + * + * @param value - The string to test. + * @param minLen - Minimum permitted length (inclusive). Defaults to 3. + * @param maxLen - Maximum permitted length (inclusive). Defaults to 20. + * @returns `true` if the string is a valid username, otherwise `false`. */ export function isUsername(value: string, minLen = 3, maxLen = 20): boolean { if (value.length < minLen || value.length > maxLen) return false @@ -40,6 +53,9 @@ export function isUsername(value: string, minLen = 3, maxLen = 20): boolean { /** * Returns true if the string is a valid Australian phone number. * Accepts formats: 04XX XXX XXX, +614XX XXX XXX, (02) XXXX XXXX, 02 XXXX XXXX + * + * @param value - The phone number to test; spaces, hyphens, dots and parentheses are ignored. + * @returns `true` if the cleaned number is a valid Australian number, otherwise `false`. */ export function isAustralianPhone(value: string): boolean { const cleaned = value.replace(/[\s\-().]/g, "")