{"id":50754905,"url":"https://github.com/moda20/typescheduler","last_synced_at":"2026-06-11T04:01:14.993Z","repository":{"id":298199447,"uuid":"986497673","full_name":"moda20/TypeScheduler","owner":"moda20","description":"A starter boilerplate for the scheduler ","archived":false,"fork":false,"pushed_at":"2026-03-26T19:46:09.000Z","size":31,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-03-27T08:22:28.108Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/moda20.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-05-19T17:43:18.000Z","updated_at":"2026-03-26T19:46:13.000Z","dependencies_parsed_at":"2025-06-10T22:01:31.844Z","dependency_job_id":null,"html_url":"https://github.com/moda20/TypeScheduler","commit_stats":null,"previous_names":["moda20/scheduler_starter","moda20/typescheduler"],"tags_count":0,"template":true,"template_full_name":null,"purl":"pkg:github/moda20/TypeScheduler","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moda20%2FTypeScheduler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moda20%2FTypeScheduler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moda20%2FTypeScheduler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moda20%2FTypeScheduler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/moda20","download_url":"https://codeload.github.com/moda20/TypeScheduler/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/moda20%2FTypeScheduler/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34181555,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-11T02:00:06.485Z","response_time":57,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-11T04:01:12.118Z","updated_at":"2026-06-11T04:01:14.960Z","avatar_url":"https://github.com/moda20.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n# TypeScheduler\n\n\u003cimg src=\".github/assets/images/TypeSchedulerLogo.png\" alt=\"Type Scheduler UI Logo\" width=\"200\" /\u003e\n\n\n\u003c/div\u003e\n\n\u003e A starter template for testing, education, development, and experimentation with TypeScheduler.\n\n![TypeScript](https://img.shields.io/badge/TypeScript-5.0+-blue.svg)\n![Docker](https://img.shields.io/badge/Docker-Compose-blue.svg)\n![License](https://img.shields.io/badge/License-ISC-green.svg)\n\n📚 **Full Documentation**: [TypeScheduler Docs](https://scheduler-docs-xi.vercel.app/)\n\u003e The documentation below provides a quick overview of the starter template. For comprehensive documentation, visit the official docs site.\n\n---\n\n## 🎯 What is TypeScheduler?\n\nTypeScheduler is a task manager that lets you schedule your own tasks written in TypeScript/JavaScript. \ninstead of using shell scripts to launch `node script.ts`, you can simply use an API or the UI to import your script, launch it, and monitor its progress \n\nBased on a typed class component, you can write custom processes using any packages, libraries, and tools you want, all while accessing a set of utilities, loggers, event handlers, and more.\n\n\u003e **In a nutshell**: TypeScheduler is a powerful, feature-rich CRON job manager.\n\n\u003cdiv align=\"center\"\u003e\n\u003cimg align=\"center\" src=\".github/assets/images/screenCapture2026_04_03.png\" alt=\"Type Scheduler UI Logo\" width=\"720\" /\u003e\n\n\u003c/div\u003e\n\n\n## ✨ Features\n\n- 📘 **TypeScript** - Fully typed with exported types for better DX\n- ⚡ **Bun Runtime** - Faster execution with [Bun](https://bun.sh) and [Elysia](https://elysiajs.com/) API framework\n- 🔄 **Lifecycle Events** - Multiple lifecycle hooks for tasks (jobs)\n- 📝 **Multi-Target Logging** - Supports files, [Loki](https://grafana.com/oss/loki/), [Gotify](https://gotify.net/docs/install), and [ntfy](https://docs.ntfy.sh/install/)\n- 🎨 **Integrated UI** - Easy-to-use API with a tightly coupled UI\n- 🌐 **Built-in Networking** - Includes [axios](https://axios-http.com/docs/intro) for HTTP requests (more tools coming soon)\n- 🔐 **Authentication** - JWT-based auth for both API and UI\n\n## 🚀 Quick Start\n\nGet up and running in 3 steps:\n\n```bash\n# 1. Pull the latest Docker images\ndocker-compose pull\n\n# 2. Copy the auto-generated TypeScript types from the backend image\ndocker create --name=scc_b ghcr.io/moda20/scheduler_backend:latest \u0026\u0026 \\\ndocker cp scc_b:/usr/src/app/extraTypes/types.d.ts ./types.d.ts \u0026\u0026 \\\ndocker container rm scc_b\n\n# the types.d.ts file copied will have all the types needed to code your job and when using the injected features like logging and notifications, an example job show how is it used\n\n# 3. Start the stack\ndocker-compose up -d\n```\n\n\u003e The UI will be available at `http://localhost:9002` (updatable in the compose file)\n\n\n\n## Merged deployment (backend server + frontend web ui): \n\nOther than the compose file used in the quickstart steps above, a single container service is possible that combines the UI and backend, \nthis is useful if you have no need to keep track of the latest releases in both projects separately, or you are not going to modify the \ncontainer image parameters. \n\nThe single container deployment uses the `[Dockerfile.merged](Dockerfile.merged)` dockerfile and the [docker-compose.merged.yml](docker-compose.merged.yml) for your compose config.\nThe types generation command are still the same except for the image name, if you are going to build the image locally change the name to the name seen in your \nterminal windows. the default name should be `scheduler_app:latest`\n\n```bash\n# 1. Pull the latest Docker image using the merged dockerfile (or ignore this step if you are building it locally)\ndocker-compose -f docker-compose.merged.yml pull\n\n# 2. Copy the auto-generated TypeScript types from the backend image\ndocker create --name=scc_b ghcr.io/moda20/scheduler_app:latest \u0026\u0026 \\\ndocker cp scc_b:/usr/src/app/extraTypes/types.d.ts ./types.d.ts \u0026\u0026 \\\ndocker container rm scc_b\n\n# the types.d.ts file copied will have all the types needed to code your job and when using the injected features like logging and notifications, an example job show how is it used\n\n# 3. Start the stack\ndocker-compose -f docker-compose.merged.yml up -d\n```\n\n---\n\n## 📋 Prerequisites \u0026 Services\n\nThe starter template uses Docker Compose to launch the \"TypeScheduler Stack\"—a combination of services that handle all available features. Not all services are mandatory.\n\n### Services Overview\n\n| Service | Description | Required |\n|---------|-------------|----------|\n| `scheduler_backend` | Main backend that manages jobs | ✅ Yes |\n| `scheduler_ui` | Web UI for managing jobs | ✅ Yes |\n| `mysql` | Database for jobs and authentication | ✅ Yes |\n| `gotify` | Notification server | ❌ Optional |\n| `loki` | Grafana Loki logging server | ❌ Optional |\n\n---\n\n## ⚙️ Configuration Guide\n\n### Setting Up the Database\n\nTypeScheduler uses MySQL and requires **2 databases to be created before running the backend**:\n\n```sql\nCREATE DATABASE scheduler_db;    -- For job definitions and stats, this is the default name and can be changed in the .env file\nCREATE DATABASE scheduler_base;   -- For authentication and user data, this is the default name and can be changed in the .env file\n```\n\nThe backend will automatically run any missing schema migrations on startup.\n\n### Setting Up the Backend\n\nConfigure the backend using the `.env` file. A complete `.env.example` file is provided with all default values. For detailed configuration options, see the [backend repo documentation](https://github.com/moda20/scheduler_backend#%EF%B8%8F-configuration).\n\n### Setting Up the Frontend\n\n1. Access the UI at `http://localhost:9002`\n2. Press `Command+L` (Mac) or `Alt+L` (Windows/Linux) to open the server configuration drawer\n3. Enter the backend URL: `http://localhost:8080`\n4. Optionally save the target locally for easy switching between multiple backends\n5. Refresh and login or register (no email verification required)\n\n### Configuring External Services (Optional)\n\n#### 📢 Gotify Configuration\n\nRequires 4 environment variables:\n\n| Variable | Description |\n|----------|-------------|\n| `GOTIFY_URL` | Host and port of your Gotify server (e.g., `http://localhost:9004`) |\n| `GOTIFY_TOKEN` | User token (recommend creating a dedicated user for scheduler) |\n| `GOTIFY_APP_TOKEN` | Application token for success notifications |\n| `GOTIFY_ERROR_APP_TOKEN` | Application token for error/crash notifications |\n\n#### 📊 Loki Configuration\n\nRequires 3 environment variables:\n\n| Variable | Description |\n|----------|-------------|\n| `GRAFANA_LOKI_URL` | Host and port of your Loki server |\n| `GRAFANA_LOKI_USERNAME` | Username for Loki authentication |\n| `GRAFANA_LOKI_PASSWORD` | Password for Loki authentication |\n\n#### 🔔 ntfy Configuration\n\nRequires 3 environment variables:\n\n| Variable | Description |\n|----------|-------------|\n| `NTFY_URL` | Host and port of your ntfy server |\n| `NTFY_TOKEN` | User token (recommend creating a dedicated user for scheduler) |\n| `NTFY_TOPIC` | Target ntfy topic |\n\n\u003e **Note**: Either Gotify or ntfy can be used as the default notification service, but both can also be used as regular services.\n\n---\n\n## 💻 Creating Your First Task\n\nTasks are based on the `JobConsumer` class. Check out `exampleJob.ts` for a working example.\n\n### Task Structure\n\nA task consists of:\n- **Single file** containing a class that inherits from `JobConsumer`\n- At minimum, a `run` method that executes your code\n- Ability to import any npm packages or call external services\n- Export a new instance: `export default new ExampleJob();`\n\n### JobConsumer Methods \u0026 Properties\n\n| Name | Type | Description |\n|------|------|-------------|\n| `run` | function | Main method that executes your job code |\n| `preRun` | function | Called before `run` - handles proxy injection and error management |\n| `logEvent` | function | Primary logging method - sends logs to Loki if configured |\n| `complete` | function | Call at the end of `run` to register success or errors |\n| `exportResultsToFile` | function | Export results as a generic file type |\n| `exportCacheFiles` | function | Export cache files with TTL (time-to-live) support |\n| `injectProxies` | function | Manually inject linked proxies into axios |\n| `axios` | object | Pre-configured axios instance with proxy support |\n| `notifications` | object | Send notifications via Gotify or ntfy |\n\n### Example Task\n\n```typescript\nimport { JobConsumer } from \"@jobConsumer/jobConsumer\";\nimport { JobDTO, JobLogDTO, JobOptions } from \"@types/models/job\";\n\nclass ExampleJob extends JobConsumer {\n    constructor() {\n        super();\n    }\n\n    async run(job: JobDTO, jobLog: JobLogDTO, options: JobOptions) {\n        // Log an event\n        this.logEvent(\"Starting example job\");\n\n        // Make HTTP request using built-in axios\n        const response = await this.axios.get(\"https://api.example.com/data\");\n\n        // Export results\n        await this.exportResultsToFile({\n            job_log_id: jobLog.id,\n            fileName: \"results\",\n            results: { data: response.data },\n        });\n\n        // Export cache with TTL\n        await this.exportCacheFiles({\n            job_log_id: jobLog.id,\n            fileName: \"cache\",\n            data: { cached: response.data },\n            newFile: true,\n        });\n\n        // Mark job as complete\n        return this.complete(jobLog, \"\");\n    }\n}\n\nexport default new ExampleJob();\n```\n\n### Adding Tasks to TypeScheduler\n\nYou can add tasks via the API, but it's much easier through the UI:\n1. Click `+ New Job` on the main jobs list\n2. Select your task file\n3. Enter a unique name\n4. Set the cron schedule\n5. Save!\n\n---\n\n## 📸 Screenshots \u0026 Demos\n\n### Authentication \u0026 Setup\n\n| Login Page | Server Target Configuration | Server with Target Set |\n|-----------|----------------------------|------------------------|\n| ![](https://i.imgur.com/bQ4astX.png) | ![](https://i.imgur.com/I7oCOsW.png) | ![](https://i.imgur.com/Crbao21.png) |\n\n### Job Management\n\n| New Job Popup | Job Popup with Fields | Jobs List | Job Running |\n|---------------|---------------------|-----------|-------------|\n| ![](https://i.imgur.com/Divijwd.png) | ![](https://i.imgur.com/iELOClq.png) | ![](https://i.imgur.com/dfd7SkE.png) | ![](https://i.imgur.com/xXYfmMH.png) |\n\n### Job Details \u0026 Actions\n\n| Loki Logs | Output Files \u0026 Cache | Scheduling Popup | Quick Search |\n|-----------|---------------------|-----------------|--------------|\n| ![](https://i.imgur.com/amxv1a1.png) | ![](https://i.imgur.com/oBa2kMO.png) | ![](https://i.imgur.com/yLLcYKV.png) | ![](https://i.imgur.com/pRQTVpM.png) |\n\n### System Management\n\n| Database Dashboard | Proxies List |\n|-------------------|--------------|\n| ![](https://i.imgur.com/NCnYZAT.png) | ![](https://i.imgur.com/zTwSX2E.png) |\n\n---\n\n## 🤝 Contributing\n\nContributions are welcome! I ([@moda20](https://github.com/moda20)) review all PRs and test them personally. To accelerate the review process, please include:\n\n- Clear description of changes\n- Testing steps and results\n- Any relevant screenshots or logs\n\nThis applies to all TypeScheduler services (backend \u0026 frontend) as well.\n\n---\n\n## 📄 License\n\nISC License - see [LICENSE](LICENSE) for details\n\n---\n\n## 🔗 Links\n\n- 📖 [Full Documentation](https://scheduler-docs-xi.vercel.app/)\n- 🐛 [Backend Repository](https://github.com/moda20/TypeSchedulerBackend)\n- 🐛 [Frontend Repository](https://github.com/moda20/TypeSchedulerUI)\n- 👤 [Author](https://github.com/moda20)\n\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoda20%2Ftypescheduler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmoda20%2Ftypescheduler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmoda20%2Ftypescheduler/lists"}