Self-hosted multi-platform broadcast newsroom for activist collectives: publishing pipeline with group approval and DST-proof scheduling, TweetDeck-style column wall with hostile-content-safe rendering, live control room with Auto Director, bridged chat governance with polls and quorum, distributed sandboxed transcode workers, encrypted content-addressed archive, monthly analytics. MIT licensed. See README.md and docs/.
58 lines
2.3 KiB
TypeScript
58 lines
2.3 KiB
TypeScript
/**
|
|
* @tactical-media-broadcast-hub/scheduling — shared schedule time semantics (WP3, reused by WP13).
|
|
*
|
|
* A schedule is a five-field cron expression plus an explicit IANA timezone
|
|
* (never server-local; UTC allowed). Occurrences are evaluated in that zone as
|
|
* nominal local times, then materialized to UTC fire instants. The occurrence
|
|
* key is the materialized UTC instant, so `UNIQUE (workspace_id, schedule_id,
|
|
* fire_at_utc)` holds by construction.
|
|
*
|
|
* - DST gap: a nonexistent local time fires at the first valid instant after
|
|
* the gap (shift forward).
|
|
* - DST fold: an ambiguous local time fires once, at its earlier instant.
|
|
* - Collapse: several nominal local times mapping onto one post-gap instant
|
|
* yield exactly one occurrence.
|
|
* - Re-materialization on tzdata/timezone change deletes unclaimed future
|
|
* occurrences and regenerates only strictly-later slots, never refiring a
|
|
* slot already fired under the old zone.
|
|
*
|
|
* Pure functions only: no app, DB or Temporal imports.
|
|
*/
|
|
export {
|
|
SchedulingError,
|
|
InvalidCronError,
|
|
InvalidTimezoneError,
|
|
InvalidNominalLocalError,
|
|
InvalidInstantError,
|
|
ImpossibleScheduleError,
|
|
} from "./errors.js";
|
|
export {
|
|
canonicalTimezone,
|
|
isValidTimezone,
|
|
assertValidTimezone,
|
|
wallOfInstant,
|
|
offsetMs,
|
|
toInstantMs,
|
|
currentTzdataVersion,
|
|
epochOfWall,
|
|
} from "./timezone.js";
|
|
export type { WallClock, NominalLocal } from "./timezone.js";
|
|
export { parseCron, cronMatchesDay, cronMatchesTime, FIELD_NAMES } from "./cron.js";
|
|
export type { ParsedCron, CronField } from "./cron.js";
|
|
export { formatNominal, parseNominal, compareWall, wallEquals, wallAsEpochMs } from "./nominal.js";
|
|
export { resolveWallToInstant } from "./materialize.js";
|
|
export { materializeOccurrence } from "./materialize-api.js";
|
|
export {
|
|
prepareSchedule,
|
|
sortedHours,
|
|
sortedMinutes,
|
|
slotNominal,
|
|
matchingLocalDays,
|
|
stepOneLocalDay,
|
|
} from "./schedule.js";
|
|
export type { ScheduleSpec, Occurrence, PreparedSchedule } from "./schedule.js";
|
|
export { nextOccurrencesPrepared } from "./occurrences.js";
|
|
export type { NextOccurrencesOptions } from "./occurrences.js";
|
|
export { nextOccurrences, materializeOccurrences } from "./occurrences_extra.js";
|
|
export { rematerialize } from "./rematerialize.js";
|
|
export type { StoredOccurrence, RematerializeOptions, RematerializeResult } from "./rematerialize.js";
|