@akumzy/cron-api-sdk
Version:
TypeScript SDK for Cron API and Reminder services
1 lines • 22.3 kB
Source Map (JSON)
{"version":3,"sources":["../src/base-client.ts","../src/jobs-client.ts","../src/reminders-client.ts","../src/services-client.ts","../src/cron-api-sdk.ts","../src/utils.ts","../src/index.ts"],"names":["axios","BaseClient","config","response","error","message","url","data","JobsClient","id","job","RemindersClient","reminder","ServicesClient","service","CronApiSDK","_CronApiSDK","baseURL","auth","CronUtils","expression","parts","minute","hour","day","month","dayOfWeek","patterns","key","value","result","days","dayNumbers","d","start","end","num","j","k","count","executions","now","current","i","date","matches","options","src_default"],"mappings":"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","sourcesContent":["import axios, { AxiosInstance, AxiosResponse } from 'axios';\nimport { CronApiConfig } from './types';\n\nexport class BaseClient {\n protected client: AxiosInstance;\n\n constructor(config: CronApiConfig) {\n this.client = axios.create({\n baseURL: config.baseURL,\n timeout: config.timeout || 10000,\n headers: {\n 'Content-Type': 'application/json',\n ...config.headers,\n },\n });\n\n // Add basic auth if provided\n if (config.auth) {\n this.client.defaults.auth = {\n username: config.auth.username,\n password: config.auth.password,\n };\n }\n\n // Add response interceptor for consistent error handling\n this.client.interceptors.response.use(\n (response: AxiosResponse) => response,\n (error) => {\n if (error.response) {\n // Server responded with error status\n const message = error.response.data?.error || error.response.statusText;\n throw new Error(`API Error (${error.response.status}): ${message}`);\n } else if (error.request) {\n // Request was made but no response received\n throw new Error('Network Error: No response received from server');\n } else {\n // Something else happened\n throw new Error(`Request Error: ${error.message}`);\n }\n },\n );\n }\n\n protected async _get<T>(url: string): Promise<T> {\n const response = await this.client.get<T>(url);\n return response.data;\n }\n\n protected async _post<T>(url: string, data?: any): Promise<T> {\n const response = await this.client.post<T>(url, data);\n return response.data;\n }\n\n protected async _put<T>(url: string, data?: any): Promise<T> {\n const response = await this.client.put<T>(url, data);\n return response.data;\n }\n\n protected async _delete<T>(url: string): Promise<T> {\n const response = await this.client.delete<T>(url);\n return response.data;\n }\n\n /**\n * Health check endpoint\n */\n public async ping(): Promise<{ message: string }> {\n return this._get<{ message: string }>('/api/ping');\n }\n}\n","import { BaseClient } from './base-client';\nimport { Job, JobLog, CreateJobRequest, UpdateJobRequest, TriggerJobResponse, CronApiConfig } from './types';\n\nexport class JobsClient extends BaseClient {\n constructor(config: CronApiConfig) {\n super(config);\n }\n\n /**\n * Get all jobs\n */\n public async getAll(): Promise<Job[]> {\n return this._get<Job[]>('/api/jobs');\n }\n\n /**\n * Get a job by ID\n */\n public async getById(id: number): Promise<Job> {\n return this._get<Job>(`/api/jobs/${id}`);\n }\n\n /**\n * Create a new job\n */\n public async create(job: CreateJobRequest): Promise<Job> {\n return this._post<Job>('/api/jobs', job);\n }\n\n /**\n * Update an existing job\n */\n public async update(job: UpdateJobRequest): Promise<Job> {\n return this._put<Job>(`/api/jobs/${job.id}`, job);\n }\n\n /**\n * Delete a job\n */\n public async delete(id: number): Promise<void> {\n return this._delete<void>(`/api/jobs/${id}`);\n }\n\n /**\n * Get logs for a specific job\n */\n public async getLogs(id: number): Promise<JobLog[]> {\n return this._get<JobLog[]>(`/api/jobs/${id}/logs`);\n }\n\n /**\n * Manually trigger a job\n */\n public async trigger(id: number): Promise<TriggerJobResponse> {\n return this._post<TriggerJobResponse>(`/api/jobs/${id}/trigger`);\n }\n\n /**\n * Get all logs across all jobs\n */\n public async getAllLogs(): Promise<JobLog[]> {\n return this._get<JobLog[]>('/api/logs');\n }\n}\n","import { BaseClient } from './base-client';\nimport {\n Reminder,\n ReminderLog,\n CreateReminderRequest,\n UpdateReminderRequest,\n TriggerReminderResponse,\n CronApiConfig,\n} from './types';\n\nexport class RemindersClient extends BaseClient {\n constructor(config: CronApiConfig) {\n super(config);\n }\n\n /**\n * Get all reminders\n */\n public async getAll(): Promise<Reminder[]> {\n return this._get<Reminder[]>('/api/reminders');\n }\n\n /**\n * Get a reminder by ID\n */\n public async getById(id: string): Promise<Reminder> {\n return this._get<Reminder>(`/api/reminders/${id}`);\n }\n\n /**\n * Create a new reminder\n */\n public async create(reminder: CreateReminderRequest): Promise<Reminder> {\n return this._post<Reminder>('/api/reminders', reminder);\n }\n\n /**\n * Update an existing reminder\n */\n public async update(reminder: UpdateReminderRequest): Promise<Reminder> {\n return this._put<Reminder>(`/api/reminders/${reminder.id}`, reminder);\n }\n\n /**\n * Delete a reminder\n */\n public async delete(id: string): Promise<void> {\n return this._delete<void>(`/api/reminders/${id}`);\n }\n\n /**\n * Get logs for a specific reminder\n */\n public async getLogs(id: string): Promise<ReminderLog[]> {\n return this._get<ReminderLog[]>(`/api/reminders/${id}/logs`);\n }\n\n /**\n * Manually trigger a reminder\n */\n public async trigger(id: string): Promise<TriggerReminderResponse> {\n return this._post<TriggerReminderResponse>(`/api/reminders/${id}/trigger`);\n }\n\n /**\n * Get all reminder logs across all reminders\n */\n public async getAllLogs(): Promise<ReminderLog[]> {\n return this._get<ReminderLog[]>('/api/reminder-logs');\n }\n}\n","import { BaseClient } from './base-client';\nimport { Service, CreateServiceRequest, UpdateServiceRequest, CronApiConfig } from './types';\n\nexport class ServicesClient extends BaseClient {\n constructor(config: CronApiConfig) {\n super(config);\n }\n\n /**\n * Get all services\n */\n public async getAll(): Promise<Service[]> {\n return this._get<Service[]>('/api/services');\n }\n\n /**\n * Get a service by ID\n */\n public async getById(id: string): Promise<Service> {\n return this._get<Service>(`/api/services/${id}`);\n }\n\n /**\n * Create a new service\n */\n public async create(service: CreateServiceRequest): Promise<Service> {\n return this._post<Service>('/api/services', service);\n }\n\n /**\n * Update an existing service\n */\n public async update(service: UpdateServiceRequest): Promise<Service> {\n return this._put<Service>(`/api/services/${service.id}`, service);\n }\n\n /**\n * Delete a service\n */\n public async delete(id: string): Promise<void> {\n return this._delete<void>(`/api/services/${id}`);\n }\n}\n","import { JobsClient } from './jobs-client';\nimport { RemindersClient } from './reminders-client';\nimport { ServicesClient } from './services-client';\nimport { CronApiConfig } from './types';\n\nexport class CronApiSDK {\n public readonly jobs: JobsClient;\n public readonly reminders: RemindersClient;\n public readonly services: ServicesClient;\n\n constructor(config: CronApiConfig) {\n this.jobs = new JobsClient(config);\n this.reminders = new RemindersClient(config);\n this.services = new ServicesClient(config);\n }\n\n /**\n * Test connection to the API\n */\n public async ping(): Promise<{ message: string }> {\n return this.jobs.ping();\n }\n\n /**\n * Create SDK instance with default configuration\n */\n public static create(baseURL: string, auth?: { username: string; password: string }): CronApiSDK {\n return new CronApiSDK({\n baseURL,\n auth,\n });\n }\n\n /**\n * Create SDK instance for development\n */\n public static createForDev(auth?: { username: string; password: string }): CronApiSDK {\n return new CronApiSDK({\n baseURL: 'http://localhost:8080',\n auth,\n });\n }\n}\n","/**\n * Utility functions for working with cron expressions and scheduling\n */\nexport class CronUtils {\n /**\n * Validate a cron expression\n * Basic validation for standard 5-field cron expressions\n */\n public static validateCronExpression(expression: string): boolean {\n if (!expression || typeof expression !== 'string') {\n return false;\n }\n\n const parts = expression.trim().split(/\\s+/);\n\n // Should have 5 parts: minute, hour, day, month, day-of-week\n if (parts.length !== 5) {\n return false;\n }\n\n const [minute, hour, day, month, dayOfWeek] = parts;\n\n // Basic validation patterns\n const patterns = {\n minute: /^(\\*|([0-5]?\\d)(,([0-5]?\\d))*|([0-5]?\\d)-([0-5]?\\d)|(\\*\\/([1-9]\\d*)))$/,\n hour: /^(\\*|(1?\\d|2[0-3])(,(1?\\d|2[0-3]))*|(1?\\d|2[0-3])-(1?\\d|2[0-3])|(\\*\\/([1-9]\\d*)))$/,\n day: /^(\\*|([1-9]|[12]\\d|3[01])(,([1-9]|[12]\\d|3[01]))*|([1-9]|[12]\\d|3[01])-([1-9]|[12]\\d|3[01])|(\\*\\/([1-9]\\d*)))$/,\n month: /^(\\*|([1-9]|1[0-2])(,([1-9]|1[0-2]))*|([1-9]|1[0-2])-([1-9]|1[0-2])|(\\*\\/([1-9]\\d*)))$/,\n dayOfWeek: /^(\\*|[0-6](,[0-6])*|[0-6]-[0-6]|(\\*\\/([1-7])))$/,\n };\n\n return (\n patterns.minute.test(minute) &&\n patterns.hour.test(hour) &&\n patterns.day.test(day) &&\n patterns.month.test(month) &&\n patterns.dayOfWeek.test(dayOfWeek)\n );\n }\n\n /**\n * Common cron expressions\n */\n public static readonly commonExpressions = {\n everyMinute: '* * * * *',\n every5Minutes: '*/5 * * * *',\n every15Minutes: '*/15 * * * *',\n every30Minutes: '*/30 * * * *',\n everyHour: '0 * * * *',\n everyDay: '0 0 * * *',\n everyWeek: '0 0 * * 0',\n everyMonth: '0 0 1 * *',\n everyYear: '0 0 1 1 *',\n weekdays: '0 9 * * 1-5',\n weekends: '0 10 * * 0,6',\n };\n\n /**\n * Parse cron expression into human-readable format\n */\n public static parseCronExpression(expression: string): string {\n if (!this.validateCronExpression(expression)) {\n return 'Invalid cron expression';\n }\n\n // Check against common expressions first\n for (const [key, value] of Object.entries(this.commonExpressions)) {\n if (value === expression) {\n return this.humanizeCommonExpression(key);\n }\n }\n\n const [minute, hour, day, month, dayOfWeek] = expression.split(/\\s+/);\n\n let result = 'At ';\n\n // Handle minute and hour\n if (minute === '*' && hour === '*') {\n result += 'every minute';\n } else if (minute === '0' && hour === '*') {\n result += 'every hour';\n } else if (minute === '0' && hour !== '*') {\n result += `${hour}:00`;\n } else if (minute !== '*' && hour !== '*') {\n result += `${hour}:${minute.padStart(2, '0')}`;\n } else {\n result += `minute ${minute} of every hour`;\n }\n\n // Handle day, month, day of week\n if (day !== '*' || month !== '*' || dayOfWeek !== '*') {\n result += ' on ';\n\n if (dayOfWeek !== '*') {\n const days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];\n if (dayOfWeek.includes(',')) {\n const dayNumbers = dayOfWeek.split(',').map((d) => parseInt(d));\n result += dayNumbers.map((d) => days[d]).join(', ');\n } else if (dayOfWeek.includes('-')) {\n const [start, end] = dayOfWeek.split('-').map((d) => parseInt(d));\n result += `${days[start]} through ${days[end]}`;\n } else {\n result += days[parseInt(dayOfWeek)];\n }\n }\n\n if (day !== '*') {\n result += ` the ${day}${this.getOrdinalSuffix(parseInt(day))}`;\n }\n\n if (month !== '*') {\n const months = [\n 'January',\n 'February',\n 'March',\n 'April',\n 'May',\n 'June',\n 'July',\n 'August',\n 'September',\n 'October',\n 'November',\n 'December',\n ];\n result += ` of ${months[parseInt(month) - 1]}`;\n }\n }\n\n return result;\n }\n\n private static humanizeCommonExpression(key: string): string {\n const map: Record<string, string> = {\n everyMinute: 'Every minute',\n every5Minutes: 'Every 5 minutes',\n every15Minutes: 'Every 15 minutes',\n every30Minutes: 'Every 30 minutes',\n everyHour: 'Every hour',\n everyDay: 'Every day at midnight',\n everyWeek: 'Every week on Sunday at midnight',\n everyMonth: 'Every month on the 1st at midnight',\n everyYear: 'Every year on January 1st at midnight',\n weekdays: 'Every weekday at 9:00 AM',\n weekends: 'Every weekend at 10:00 AM',\n };\n return map[key] || key;\n }\n\n private static getOrdinalSuffix(num: number): string {\n const j = num % 10;\n const k = num % 100;\n if (j === 1 && k !== 11) return 'st';\n if (j === 2 && k !== 12) return 'nd';\n if (j === 3 && k !== 13) return 'rd';\n return 'th';\n }\n\n /**\n * Get next execution times for a cron expression\n * Note: This is a simplified implementation\n */\n public static getNextExecutions(expression: string, count: number = 5): Date[] {\n if (!this.validateCronExpression(expression)) {\n return [];\n }\n\n const executions: Date[] = [];\n const now = new Date();\n let current = new Date(now.getTime() + 60000); // Start from next minute\n\n // Simplified calculation - in production, use a proper cron parser library\n const [minute, hour, day, month, dayOfWeek] = expression.split(/\\s+/);\n\n for (let i = 0; i < count && executions.length < count; i++) {\n if (this.matchesCronExpression(current, minute, hour, day, month, dayOfWeek)) {\n executions.push(new Date(current));\n }\n current = new Date(current.getTime() + 60000); // Add 1 minute\n }\n\n return executions;\n }\n\n private static matchesCronExpression(\n date: Date,\n minute: string,\n hour: string,\n day: string,\n month: string,\n dayOfWeek: string,\n ): boolean {\n // Simplified matching - in production, use a proper cron parser\n const matches = {\n minute: minute === '*' || parseInt(minute) === date.getMinutes(),\n hour: hour === '*' || parseInt(hour) === date.getHours(),\n day: day === '*' || parseInt(day) === date.getDate(),\n month: month === '*' || parseInt(month) === date.getMonth() + 1,\n dayOfWeek: dayOfWeek === '*' || parseInt(dayOfWeek) === date.getDay(),\n };\n\n return Object.values(matches).every(Boolean);\n }\n\n /**\n * Create a cron expression from components\n */\n public static createCronExpression(options: {\n minute?: number | string;\n hour?: number | string;\n day?: number | string;\n month?: number | string;\n dayOfWeek?: number | string;\n }): string {\n const { minute = '*', hour = '*', day = '*', month = '*', dayOfWeek = '*' } = options;\n\n return `${minute} ${hour} ${day} ${month} ${dayOfWeek}`;\n }\n}\n","import { CronApiSDK } from './cron-api-sdk';\n\n// Main SDK exports\nexport { CronApiSDK } from './cron-api-sdk';\nexport { JobsClient } from './jobs-client';\nexport { RemindersClient } from './reminders-client';\nexport { ServicesClient } from './services-client';\nexport { BaseClient } from './base-client';\n\n// Type exports\nexport type {\n Job,\n JobLog,\n Service,\n Reminder,\n ReminderLog,\n ReminderType,\n ReminderStatus,\n CronApiConfig,\n CreateJobRequest,\n UpdateJobRequest,\n CreateReminderRequest,\n UpdateReminderRequest,\n CreateServiceRequest,\n UpdateServiceRequest,\n TriggerJobResponse,\n TriggerReminderResponse,\n ApiResponse,\n} from './types';\n\n// Utility exports\nexport { CronUtils } from './utils';\n\n// Default export\nexport default CronApiSDK;\n"]}