first commit
This commit is contained in:
@@ -0,0 +1,45 @@
|
||||
# job-snapshot
|
||||
|
||||
## Purpose
|
||||
|
||||
Projects a mutable `ScheduledJob` record (the scheduler's internal data structure) to an immutable `JobStatus` snapshot for public consumption via `JobScheduler.jobs()`. Extracted into its own module so the scheduler core stays under the 300-line hard limit and so the shape transformation has a single obvious home.
|
||||
|
||||
## Features
|
||||
|
||||
- Pure function — no side effects, no allocation beyond the returned object.
|
||||
- Honours `exactOptionalPropertyTypes` by conditionally spreading optional fields.
|
||||
- Output object is safe to freeze at the caller.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { snapshotJob } from "@suaveplan/job-scheduler";
|
||||
|
||||
const status = snapshotJob(internalJobRecord);
|
||||
console.log(status.id, status.status, status.runs);
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { snapshotJob } from "@suaveplan/job-scheduler";
|
||||
|
||||
function adminDashboard(jobs: Iterable<ScheduledJob>): JobStatus[] {
|
||||
const out: JobStatus[] = [];
|
||||
for (const j of jobs) {
|
||||
const snap = snapshotJob(j);
|
||||
if (snap.failures > 0) out.push(snap);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
- `snapshotJob(job: ScheduledJob): JobStatus` — returns a plain object with every public field of `JobStatus`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The conditional spread (`...(value !== undefined ? { key: value } : {})`) is required because the repo TSConfig sets `exactOptionalPropertyTypes: true` — assigning `undefined` to an optional field is a compile-time error. Inline-spreading a guard object is the smallest pattern that preserves the omit-vs-undefined distinction. The function deliberately does not freeze its return value; the caller decides whether to freeze the whole array or each individual entry.
|
||||
|
||||
Keeping this projection in its own module rather than inlining inside the scheduler class has two side benefits: first, the scheduler core stays under the 300-line file budget that the repo enforces; second, unit-testing the projection in isolation is trivial because every input field can be exercised without spinning up a full scheduler, a queue, and an event bus. The trade-off — a single extra import in `job-scheduler.ts` — is negligible, especially because the function is small enough that the bundler inlines it during tree-shaking anyway. When new optional fields are added to `JobStatus`, the only place that needs updating is this file plus the `JobStatus` type definition, which is exactly where the change should live.
|
||||
Reference in New Issue
Block a user