T-HUB/packages/scheduling/src/index.ts
glass beadian aa5e262f3a Tactical Media Broadcast Hub — initial release
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/.
2026-10-10 11:56:42 +00:00

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";