ToolUp.Scheduling.Core 0.26.0

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet add package ToolUp.Scheduling.Core --version 0.26.0
                    
NuGet\Install-Package ToolUp.Scheduling.Core -Version 0.26.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="ToolUp.Scheduling.Core" Version="0.26.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="ToolUp.Scheduling.Core" Version="0.26.0" />
                    
Directory.Packages.props
<PackageReference Include="ToolUp.Scheduling.Core" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add ToolUp.Scheduling.Core --version 0.26.0
                    
#r "nuget: ToolUp.Scheduling.Core, 0.26.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package ToolUp.Scheduling.Core@0.26.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=ToolUp.Scheduling.Core&version=0.26.0
                    
Install as a Cake Addin
#tool nuget:?package=ToolUp.Scheduling.Core&version=0.26.0
                    
Install as a Cake Tool

ToolUp.Scheduling

Domain-neutral booking-and-availability subsystem for ToolUp.Platform. Companion package — apps that don't import ToolUp.Scheduling.Server.props / ToolUp.Scheduling.Client.props pay zero runtime cost.

What this is

A small, opinionated booking primitive: bookable resources with default availability and availability exceptions, bookings that can recur via RFC 5545 RRULE, and conflict detection that surfaces every reason at once. Plus an iCalendar (.ics) parser + emitter for export / import.

Shipped surface (commit-stable across Phase 20):

Concern File Module
Domain types Shared/SchedulingTypes.fs BookableResource, Booking, AvailabilityException, RecurrenceRule, BookingConflict, BookingError
Recurrence expansion Shared/RecurrenceExpander.fs expand, occurrenceStarts — pure, Fable-safe
Wire contract Shared/SchedulingApi.fs ISchedulingApi (ToolUp.Remoting)
iCalendar I/O Shared/iCalendar.fs parse, emit, VCalendar, VEvent
Audit payloads Shared/SchedulingEvents.fs BookingCreatedPayload etc., SourceModule = "_scheduling"
Server interface Server/IBookingScheduler.fs IBookingScheduler — six-rule portable
Pure conflict detection Server/BookingConflictDetector.fs detect, DetectorInputs
Default impl Server/BookingScheduler.fs BookingScheduler over IEntityStore + IEventStore
API handler Server/SchedulingApiHandler.fs schedulingApi ToolUp.Remoting handler
Compose pipeline Server/SchedulingCompose.fs SchedulingServerApp record + run

Why a companion, not core SDK

Booking is a domain capability, not platform substrate. Nothing else in the SDK depends on IBookingScheduler. Analytics-only deployments never need scheduling — charging them the binary weight is wrong-by-default. This is the same rationale for ToolUp.AI / ToolUp.RAG / ToolUp.KnowledgeBase not living in ToolUp.Platform.

The companion is a consumer of substrate (IEntityStore Phase 19, IEventStore Phase 6, optionally IJobScheduler Phase 9b for reminders), not substrate itself.

How to enable

In your server .fsproj:

<Import Project="..\ToolUp.Scheduling\ToolUp.Scheduling.Server.props" />

In your client .fsproj (only if you'll use the planned Feliz components):

<Import Project="..\ToolUp.Scheduling\ToolUp.Scheduling.Client.props" />

In your server's composition root:

open ToolUp.Scheduling.SchedulingCompose

let config = {
    ServerConfig.defaults with
        Port = 5000
        Surfaces = Surfaces.team
        EntityStore = EnabledEntityStore   // REQUIRED — scheduling rides on Phase 19
}

[<EntryPoint>]
let main _ =
    SchedulingServerApp.create ()
    |> SchedulingServerApp.withConfig config
    |> SchedulingServerApp.withAuth (StaticJwtAuthProvider(...))
    |> SchedulingServerApp.withStorage (LocalFileStorage("data"))
    |> SchedulingServerApp.addModules myModules
    |> SchedulingServerApp.run

SchedulingServerApp.run:

  1. Registers three entity types with IEntityStore via ServerApp.withEntity:
    • BookableResource (index on ResourceType)
    • Booking (indexes on ResourceId, Status, compound (ResourceId, StartUtc))
    • AvailabilityException (index on ResourceId)
  2. Registers IBookingScheduler in DI as a singleton (default impl: BookingScheduler).
  3. Mounts the ISchedulingApi ToolUp.Remoting handler.
  4. Delegates the rest to ServerApp.run.

Apps without ServerConfig.EntityStore = EnabledEntityStore get a runtime null reference at first dispatch — explicit enforcement is a follow-up.

How to register a resource type

BookableResource.ResourceType is a free-form string ("Person", "Room", "Equipment", or your domain's term). The SDK never names a resource type — that's the deployment's choice. The same IBookingScheduler instance handles every resource type the deployment uses.

let alice : BookableResource = {
    Id = "alice@team"
    Type = "BookableResource"
    Version = 1
    ResourceType = "Person"
    DisplayName = "Alice"
    Timezone = "Europe/London"
    DefaultAvailability = [
        {
            DayOfWeek = None                  // every day
            StartTime = TimeOnly(9, 0)
            EndTime = TimeOnly(17, 0)
            EffectiveFrom = None
            EffectiveTo = None
        }
    ]
    Metadata = Map.empty
}

scheduler.RegisterResource("team-acme", alice)

How to configure reminders

Reminder fusion is opt-in and currently a no-op flag (SchedulingServerApp.withReminders). When the feature lands, the consumer enables it via:

SchedulingServerApp.create ()
|> SchedulingServerApp.withReminders        // future: lead-time + transport config
|> SchedulingServerApp.run

Until then, deployments that want booking reminders dispatch them themselves via IJobScheduler against _scheduling events — same plumbing the future fusion will use.

RRULE subset

RecurrenceExpander and the iCalendar layer cover:

  • FREQ=DAILY|WEEKLY|MONTHLY|YEARLY
  • INTERVAL=N
  • BYDAY=MO,TU,...,SU (Weekly only — token weekdays, no positional offsets)
  • UNTIL=YYYYMMDDTHHMMSSZ
  • COUNT=N

Plus a hard cap of 10,000 occurrences to defend against pathological rules. Caller detects the cap by comparing the returned list length to the hard cap.

Not supported: positional BYDAY (1MO, -1FR), BYMONTHDAY, BYSETPOS, sub-day frequencies. Deferred to Phase 20 follow-ups if customer demand emerges.

iCalendar coverage

Parser + emitter cover the VEVENT subset: UID / SUMMARY / DTSTART / DTEND / DTSTAMP / RRULE / DESCRIPTION. Datetime forms: UTC (YYYYMMDDTHHMMSSZ), floating + TZID (lifted to UTC via TimeZoneInfo.FindSystemTimeZoneById), date-only (midnight UTC). Line discipline: parser unfolds CRLF or LF + leading-whitespace; emitter folds at 75 octets. Round-trip-tested against synthetic Apple Calendar / Outlook / Google Calendar fixture excerpts (see Tests/InProcess/iCalendarTests.fs).

Not supported: VTODO / VJOURNAL / VFREEBUSY / VTIMEZONE definitions, X-properties (silently dropped on parse, never emitted), positional BYDAY / BYMONTHDAY / BYSETPOS, ATTENDEE / ORGANIZER. No paid dependencies (RFC 5545 is open; pure F# implementation, no Ical.Net).

See also

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on ToolUp.Scheduling.Core:

Package Downloads
ToolUp.Scheduling.Server

ToolUp.Scheduling Server — booking scheduler with per-resource concurrency lock, conflict detector, scheduling API handler, SchedulingCompose. Depends on ToolUp.Platform.Server + ToolUp.Scheduling.Core.

ToolUp.Calendar.CalDAV

Generic CalDAV ICalendarBridge for ToolUp.Scheduling — RFC 4791 PROPFIND / REPORT / PUT / DELETE over BCL HttpClient, credentials from ISecretStore. No vendor SDK, no OAuth registration.

ToolUp.Calendar.Microsoft

Microsoft Graph ICalendarBridge for ToolUp.Scheduling — Outlook / Microsoft 365 calendars over the Graph REST surface with BCL HttpClient: delegated OAuth through the platform substrate, calendarView delta pulls, change-notification subscriptions with their own notification route. No Graph SDK.

ToolUp.Calendar.Google

Google Calendar ICalendarBridge for ToolUp.Scheduling — the Calendar v3 REST surface over BCL HttpClient: push with deterministic event ids, incremental pull on sync tokens, watch-channel notifications with scheduled renewal and a polling fallback. OAuth through the platform's Authorization Code and token-refresh substrates. No Google client library.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.34.1 0 10/27/2026
0.34.0 55 10/26/2026
0.33.0 72 10/25/2026
0.32.0 75 10/24/2026
0.31.0 95 10/22/2026
0.30.0 118 10/20/2026
0.29.0 120 10/19/2026
0.28.0 120 10/19/2026
0.27.0 120 10/16/2026
0.26.0 119 10/12/2026
0.25.1 119 10/9/2026
0.24.1 130 10/6/2026
0.23.0 128 9/23/2026
0.22.0 119 8/27/2026
0.21.0 127 8/26/2026
0.20.1 139 8/20/2026
0.20.0 120 8/19/2026