Skip to content

Develop#9

Merged
Zaiidmo merged 7 commits intomasterfrom
develop
Apr 10, 2026
Merged

Develop#9
Zaiidmo merged 7 commits intomasterfrom
develop

Conversation

@saadmoumou
Copy link
Copy Markdown
Contributor

Summary

  • What does this PR change?

Why

  • Why is this change needed?

Checklist

  • Added/updated tests (if behavior changed)
  • npm run lint passes
  • npm run typecheck passes
  • npm test passes
  • npm run build passes
  • Added a changeset (npx changeset) if this affects consumers

Notes

  • Anything reviewers should pay attention to?

Zaiidmo and others added 6 commits April 1, 2026 21:04
* feat(COMPT-75): define typed scheduled job contracts and IScheduler port

- Add ScheduledJob type: name, handler, and one of cron | interval | timeout
- Add IScheduler interface: schedule, unschedule, reschedule, list
- Add ScheduledJobStatus type: name, cron, lastRun, nextRun, isRunning
- Add DuplicateJobError thrown when registering a duplicate job name
- Enforce cron/interval/timeout mutual exclusivity via discriminated union
- Add CronExpression named constants for human-readable schedules
- Add cron fluent builder: dailyAt, weeklyOn, monthlyOn, every().minutes()
- Update tsconfig.build.json: CommonJS output, Task 1 files only
- Update package.json: name @ciscode/scheduler-kit, version 0.0.0

* test(COMPT-75): add unit tests for CronExpression and cron builder

* feat(COMPT-75): add ScheduledJobStatus type and status/listStatus methods

- Add ScheduledJobStatus type: name, cron, lastRun, nextRun, isRunning
- Add status(name) and listStatus() to IScheduler interface and SchedulerService
- Track lastRun timestamp after each execution
- Store cronJob reference for nextRun via cronJob.nextDate()
- Export ScheduledJobStatus from public API
- Fix lint: no-misused-promises, no-floating-promises, prettier formatting

* style(COMPT-75): format all files with prettier

---------

Co-authored-by: saad moumou <saad.moumou.coder@gmail.com>
* feat(COMPT-76): NestJS SchedulerModule and SchedulerService integration

- SchedulerModule.register() and registerAsync() dynamic module factories
- SchedulerService: schedule(), reschedule(), unschedule(), list(), status(), listStatus()
- @Cron, @interval, @timeout decorators with optional job name
- MetadataScanner auto-discovers decorated provider methods on onModuleInit
- DuplicateJobError guard against double registration
- IScheduler interface and ScheduledJobStatus type
- CronExpression constants and cron fluent builder
- Full unit test coverage across module, service and decorators

* test(COMPT-76): add unit tests for CronExpression and cron builder

---------

Co-authored-by: saad moumou <saad.moumou.coder@gmail.com>
* chore(COMPT-77): scope index.ts and tsconfig.build.json to COMPT-77 files only

* test(COMPT-77): add tests for status, listStatus, cron jobs and default onJobError

* chore(COMPT-77): restore index.ts and tsconfig.build.json to develop baseline

---------

Co-authored-by: saad moumou <saad.moumou.coder@gmail.com>
#7)

* test(COMPT-78): full coverage with Jest fake timers for all scheduling behaviors

- jest.useFakeTimers() for all time-based tests — no real waiting
- @interval: fires every N ms, stops after unschedule, does not fire before interval
- @timeout: fires exactly once, removes itself from registry, does not fire early
- schedule(): job added and fires on tick
- unschedule(): timer cleared, handler not called after removal
- reschedule(): new schedule applied atomically, old timer cancelled
- Job error: caught via onJobError, scheduler continues — other jobs unaffected
- Concurrent guard: second execution skipped when first still running (isRunning lock)
- status() / listStatus(): reflect isRunning and lastRun correctly
- @Cron: registered and unscheduled without throwing
- Default onJobError: delegates to Logger.error
- Coverage: 98.63% statements, 98.11% branches, 95.34% functions (threshold 85%)

* fix(COMPT-78): resolve SonarCloud S1186 and S4524 issues

- cron-builder.ts: parseInt -> Number.parseInt (Sonar S4524 x3)
- scheduler.decorators.spec.ts: add comments to empty stub methods (Sonar S1186 x6)
- scheduler.module.spec.ts: add comments to empty stub methods and class (Sonar S1186 x6)

---------

Co-authored-by: saad moumou <saad.moumou.coder@gmail.com>
…et (#8)

- package.json: 0.0.0 -> 0.1.0
- README: full documentation (decorators, dynamic API, concurrency guard,
  error handling, async config, cron helpers, API reference)
- .changeset/scheduler-kit-v0-1-0.md: minor bump for initial feature release

Co-authored-by: saad moumou <saad.moumou.coder@gmail.com>
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR converts the repository from a generic NestJS module template into @ciscode/scheduler-kit, adding a scheduler module/service (with decorators + cron helpers) and updating build/lint/release tooling accordingly.

Changes:

  • Added SchedulerService + SchedulerModule with decorator-based auto-registration and runtime scheduling APIs.
  • Added cron helpers (CronExpression, cron builder) plus comprehensive Jest test coverage.
  • Updated package metadata, TypeScript build config, ESLint/Husky/lint-staged configuration, and CI workflows for publishing/release checks.

Reviewed changes

Copilot reviewed 26 out of 27 changed files in this pull request and generated 5 comments.

Show a summary per file
File Description
tsconfig.eslint.json Adds *.mjs to ESLint TS project include set.
tsconfig.build.json Switches to an explicit build entry list and sets build module settings.
src/services/scheduler.service.ts Implements the in-memory scheduler registry + cron/interval/timeout execution.
src/services/scheduler.service.spec.ts Adds unit tests for scheduling behavior, concurrency guard, status APIs, and error handling.
src/scheduler.module.ts Adds a dynamic module that discovers decorated methods and registers jobs on init.
src/scheduler.module.spec.ts Adds tests for module registration and decorator auto-discovery behavior.
src/interfaces/scheduler.interface.ts Defines the public scheduler types (job/timing unions, status shape, interface).
src/index.ts Replaces template exports with the scheduler-kit public API exports.
src/errors/duplicate-job.error.ts Introduces a typed error for duplicate job names.
src/errors/duplicate-job.error.spec.ts Adds tests for the custom error behavior.
src/decorators/scheduler.decorators.ts Adds @Cron, @Interval, @Timeout decorators and metadata key.
src/decorators/scheduler.decorators.spec.ts Adds tests verifying decorator metadata correctness.
src/cron-expression.ts Adds named cron constants for common schedules.
src/cron-expression.spec.ts Adds tests for exported cron constants.
src/cron-builder.ts Adds a fluent builder (cron) for generating cron expressions.
src/cron-builder.spec.ts Adds tests for cron builder parsing and output.
README.md Rewrites README from template docs to scheduler-kit usage/docs.
package.json Renames package and adjusts deps/peers/scripts for scheduler-kit.
package-lock.json Updates lockfile for new package/dependency set.
lint-staged.config.js Switches lint-staged config export style.
eslint.config.mjs Updates ESLint config ignores and TS project config wiring.
eslint.config.js Removes the previous ESLint config file.
.husky/pre-push Updates pre-push hook commands.
.github/workflows/release-check.yml Enables PR checks on master and updates Sonar env/config formatting.
.github/workflows/publish.yml Enables publishing workflow on pushes to master and updates formatting.
.github/dependabot.yml Normalizes quoting/formatting of dependabot configuration.
.changeset/scheduler-kit-v0-1-0.md Adds a changeset describing the initial 0.1.0 release contents.

reschedule(name: string, newTiming: ScheduleTiming): void {
const entry = this.registry.get(name);
if (!entry) return;
const newJob: ScheduledJob = { ...entry.job, ...newTiming } as ScheduledJob;
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

reschedule() builds newJob via { ...entry.job, ...newTiming }. When switching between timing types this preserves the old timing key (e.g., rescheduling from cron → interval keeps cron on the object), and _createEntry() will keep treating it as a cron job. Build the new job from only { name, handler } + newTiming (or explicitly omit cron/interval/timeout from the old job) so changing timing types actually takes effect.

Suggested change
const newJob: ScheduledJob = { ...entry.job, ...newTiming } as ScheduledJob;
const newJob: ScheduledJob = {
name: entry.job.name,
handler: entry.job.handler,
...newTiming,
} as ScheduledJob;

Copilot uses AI. Check for mistakes.
Comment on lines +4 to +5
// A unique symbol used as the key for storing scheduler metadata on methods.
// Using a unique constant prevents collisions with other decorator libraries.
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This comment says the metadata key is a "unique symbol", but CISCODE_SCHEDULER_METADATA is defined as a string. Either change the constant to a Symbol(...) (and update consumers accordingly) or adjust the comment to avoid misleading readers about collision risk.

Suggested change
// A unique symbol used as the key for storing scheduler metadata on methods.
// Using a unique constant prevents collisions with other decorator libraries.
// A namespaced string constant used as the key for storing scheduler metadata on methods.
// Using a well-scoped constant helps reduce collisions with other decorator libraries.

Copilot uses AI. Check for mistakes.
Comment thread package.json
"@nestjs/common": "^10 || ^11",
"@nestjs/core": "^10 || ^11",
"@nestjs/platform-express": "^10 || ^11",
"@nestjs/schedule": "^4 || ^5",
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@nestjs/schedule is listed as a peer dependency, but the code in this PR doesn't import or use it (the scheduler uses the cron package directly). This adds an unnecessary peer requirement and will generate peer warnings (also your devDependency is @nestjs/schedule@^6.1.1 while the peer range is ^4 || ^5). Consider removing it from peerDependencies, or align the peer range with what you actually support/use.

Suggested change
"@nestjs/schedule": "^4 || ^5",

Copilot uses AI. Check for mistakes.
Comment thread .husky/pre-push
Comment on lines 1 to 2
npm run typecheck
npm run test:cov No newline at end of file
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This hook no longer has the standard Husky shebang and husky.sh bootstrap that your pre-commit hook still uses. Without it, the hook may fail to run or behave differently across environments. Restore the Husky header (or make both hooks consistent with the Husky v9 format you're using).

Copilot uses AI. Check for mistakes.
- Automatic concurrency guard — overlapping executions are silently skipped
- Per-job error isolation — handler errors are caught and reported; the scheduler continues running
- `CronExpression` enum of named cron constants
- `cron()` fluent builder with `at()`, `on()`, and `everyMinutes()` helpers
Copy link

Copilot AI Apr 10, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This changeset describes a cron() builder with at(), on(), and everyMinutes() helpers, but the actual exported API in this PR is a cron object with methods like every().minutes()/hours(), dailyAt(), weeklyOn(), etc. Please update the changeset text to match the real public API so consumers aren't misled by the release notes.

Suggested change
- `cron()` fluent builder with `at()`, `on()`, and `everyMinutes()` helpers
- `cron` scheduling helpers including `every().minutes()/hours()`, `dailyAt()`, and `weeklyOn()`

Copilot uses AI. Check for mistakes.
* release(COMPT-79): bump version to 0.1.0, rewrite README, add changeset

- package.json: 0.0.0 -> 0.1.0
- README: full documentation (decorators, dynamic API, concurrency guard,
  error handling, async config, cron helpers, API reference)
- .changeset/scheduler-kit-v0-1-0.md: minor bump for initial feature release

* fix(COMPT-79): add sonar-project.properties to fix SonarCloud quality gate

- sonar.exclusions: exclude spec files from source analysis
- sonar.tests + sonar.test.inclusions: declare spec files as test code
- fixes 31.9% coverage on new code and 4.8% duplication failures

---------

Co-authored-by: saad moumou <saad.moumou.coder@gmail.com>
@sonarqubecloud
Copy link
Copy Markdown

@Zaiidmo Zaiidmo merged commit 294e11a into master Apr 10, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants