@outbuild-company/schedule-core 1.10.2 → 1.10.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +179 -28
- package/dist/cdn/schedule-core.global.js +1 -1
- package/dist/cdn/schedule-core.global.js.map +1 -1
- package/dist/index.cjs +69 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +69 -53
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,21 +1,67 @@
|
|
|
1
|
-
|
|
1
|
+
<div align="center">
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
and critical-path calculation.
|
|
3
|
+
# Schedule Core
|
|
5
4
|
|
|
6
|
-
|
|
5
|
+
**A UI-agnostic domain engine for project schedules.**
|
|
7
6
|
|
|
8
|
-
|
|
9
|
-
npm install @outbuild-company/schedule-core
|
|
10
|
-
```
|
|
7
|
+
Activities, dependencies, working calendars, constraints, autoscheduling, and critical path — behind one typed boundary.
|
|
11
8
|
|
|
12
|
-
|
|
9
|
+
[](https://github.com/OutBuild-Construction-Software/schedule-core/actions/workflows/ci.yml)
|
|
10
|
+
[](https://www.npmjs.com/package/@outbuild-company/schedule-core)
|
|
13
11
|
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
</div>
|
|
13
|
+
|
|
14
|
+
## Why Schedule Core?
|
|
15
|
+
|
|
16
|
+
Scheduling behavior needs one authority. If dates, dependency cascades, calendar math, and summary rollups are split between a Gantt widget and application code, the same edit can acquire different meanings in different consumers.
|
|
17
|
+
|
|
18
|
+
Schedule Core owns normalized schedule state and its mutations. A consumer supplies backend data, sends typed commands, and projects the resulting changes. Rendering and storage stay at the boundary.
|
|
19
|
+
|
|
20
|
+
## Mental model
|
|
21
|
+
|
|
22
|
+
```mermaid
|
|
23
|
+
flowchart LR
|
|
24
|
+
Payload["Backend payload"] --> Normalize["Parse + normalize"]
|
|
25
|
+
Normalize --> Core
|
|
26
|
+
Command["DispatchAction"] --> Core
|
|
27
|
+
|
|
28
|
+
subgraph Engine["Schedule Core"]
|
|
29
|
+
Core["Canonical state"] --> Pipeline["Validate · mutate · derive"]
|
|
30
|
+
Pipeline --> Core
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
Pipeline --> Changes["ChangeSet"]
|
|
34
|
+
Core --> Reads["Read-only snapshots"]
|
|
35
|
+
Changes --> Consumers["UI · persistence · analytics"]
|
|
36
|
+
Reads --> Consumers
|
|
16
37
|
```
|
|
17
38
|
|
|
18
|
-
|
|
39
|
+
| Part | Contract |
|
|
40
|
+
| --- | --- |
|
|
41
|
+
| **Input** | Backend-shaped sector, activities, links, and calendars. Construction parses and normalizes them. |
|
|
42
|
+
| **State** | `ScheduleCore` owns the live activity, link, calendar, hierarchy, view-state, and history model. |
|
|
43
|
+
| **Command** | A `DispatchAction` expresses an edit, structural operation, dependency change, or synchronization event. |
|
|
44
|
+
| **Result** | Accepted commands return a `ChangeSet`; expected validation failures return `{ ok: false, reason }`. |
|
|
45
|
+
| **Consumer** | Applies projections, presents warnings, sends analytics, and performs I/O. |
|
|
46
|
+
|
|
47
|
+
## Core concepts
|
|
48
|
+
|
|
49
|
+
| Concept | Role in the engine |
|
|
50
|
+
| --- | --- |
|
|
51
|
+
| **Activities** | Tasks, milestones, and summary projects in a hierarchical schedule. |
|
|
52
|
+
| **Links** | Typed dependencies with working-time lag and effective-graph cycle guards. |
|
|
53
|
+
| **Calendars** | Working days, shifts, exceptions, and date/duration calculations. |
|
|
54
|
+
| **Constraints** | ASAP, ALAP, start-based, finish-based, and fixed-date scheduling rules. |
|
|
55
|
+
| **Autoscheduler** | Applies dependency, constraint, calendar, and parent-bound rules after relevant mutations. |
|
|
56
|
+
| **Critical path** | Computes early/late dates, slack, and critical flags through an asynchronous job. |
|
|
57
|
+
| **ChangeSet** | Entity diffs plus view state, ordering, tracking events, effects, and constraint warnings. |
|
|
58
|
+
| **History** | Undo/redo state and persistence checkpoints owned by the core instance. |
|
|
59
|
+
|
|
60
|
+
## Use it in 30 seconds
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
npm install @outbuild-company/schedule-core
|
|
64
|
+
```
|
|
19
65
|
|
|
20
66
|
```ts
|
|
21
67
|
import {
|
|
@@ -28,37 +74,142 @@ const input: ScheduleCoreInput = getScheduleInput();
|
|
|
28
74
|
const core = new ScheduleCore(input);
|
|
29
75
|
await core.ready;
|
|
30
76
|
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
77
|
+
const activity = core.getAllActivitiesView()[0];
|
|
78
|
+
if (activity) {
|
|
79
|
+
const result = await core.dispatch({
|
|
80
|
+
kind: 'inline-edit',
|
|
81
|
+
activityId: activity.id,
|
|
82
|
+
column: COLUMN.TEXT,
|
|
83
|
+
newValue: 'Updated activity'
|
|
84
|
+
});
|
|
37
85
|
|
|
38
|
-
if (!result.ok) throw new Error(result.reason);
|
|
39
|
-
applyChangeSet(result.changes);
|
|
86
|
+
if (!result.ok) throw new Error(result.reason);
|
|
87
|
+
applyChangeSet(result.changes);
|
|
88
|
+
}
|
|
40
89
|
|
|
41
90
|
core.destroy();
|
|
42
91
|
```
|
|
43
92
|
|
|
44
|
-
`getScheduleInput
|
|
45
|
-
|
|
93
|
+
`getScheduleInput()` and `applyChangeSet()` belong to the consumer. The package exports one supported root entry point; deep imports are internal.
|
|
94
|
+
|
|
95
|
+
See the [API reference](docs/API.md) for initialization, commands, read APIs, persistence, undo/redo, forks, critical path, constants, and exported types.
|
|
96
|
+
|
|
97
|
+
## What a change contains
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
interface ChangeSet {
|
|
101
|
+
source: ChangeSetSource;
|
|
102
|
+
activities: ReadonlyArray<EntityChange<CoreActivity>>;
|
|
103
|
+
links: ReadonlyArray<EntityChange<Link>>;
|
|
104
|
+
calendars: ReadonlyArray<EntityChange<Calendar>>;
|
|
105
|
+
trackingEvents: ReadonlyArray<TrackingEvent>;
|
|
106
|
+
viewState?: ReadonlyArray<ViewStateChange>;
|
|
107
|
+
order?: ReadonlyArray<BranchOrderChange>;
|
|
108
|
+
effects?: ReadonlyArray<ScheduleEffect>;
|
|
109
|
+
warnings?: ReadonlyArray<ConstraintWarning>;
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
Changes are data, not side effects. A successful dispatch updates core state; consumers decide how to render, persist, report, or transmit the returned records.
|
|
114
|
+
|
|
115
|
+
## Core invariants
|
|
116
|
+
|
|
117
|
+
- **Serialized writes.** State-changing operations on one `ScheduleCore` instance run through a single operation queue.
|
|
118
|
+
- **Isolated reads.** Public read methods return cloned snapshots or read-only collections; mutating a returned value cannot mutate core state.
|
|
119
|
+
- **Guarded commits.** A rejected dispatch restores captured mutations. A failed rollback poisons the instance instead of continuing with uncertain state.
|
|
120
|
+
- **Cycle-safe graph edits.** New dependency and hierarchy mutations are checked against the effective dependency graph. Pre-existing cycles can be inspected with `auditEffectiveGraph()`.
|
|
121
|
+
- **Explicit time units.** Duration commands accept working days; domain snapshots expose `durationHours`, and link lag is stored and exposed in working hours.
|
|
122
|
+
- **Persistence is acknowledged.** Storage remains external; a successful `persistence-acknowledge` establishes the saved checkpoint and history boundary.
|
|
123
|
+
|
|
124
|
+
The complete, code-linked contract lives in [INVARIANTS.md](INVARIANTS.md).
|
|
125
|
+
|
|
126
|
+
## Architecture principles
|
|
127
|
+
|
|
128
|
+
### One mutation boundary
|
|
129
|
+
|
|
130
|
+
Domain writes enter through `dispatch()` or `applyActivityBatch()`. Handlers validate commands, update the canonical state, run the required derived passes, and assemble one result for the consumer.
|
|
131
|
+
|
|
132
|
+
### Explicit ownership
|
|
133
|
+
|
|
134
|
+
The core owns schedule entities, temporal calculations, dependency semantics, derived fields, and change tracking. Consumers own transport, persistence execution, UI projection, and presentation of rejected commands.
|
|
135
|
+
|
|
136
|
+
### Narrow internal roles
|
|
137
|
+
|
|
138
|
+
`ScheduleState` is the store, but subsystems depend on smaller capabilities such as activity readers/writers, calendar operations, the write journal, and the autoscheduler port. Architecture tests ratchet layer boundaries and public-entry reachability.
|
|
139
|
+
|
|
140
|
+
### Legacy engines behind adapters
|
|
141
|
+
|
|
142
|
+
The package has no runtime dependency on React or the DHTMLX package. Its calendar and critical-path implementations do retain adapted legacy engine code and Gantt-shaped internal contracts. The application-side bridge projects `ChangeSet` data into DHTMLX; that bridge remains outside this package.
|
|
143
|
+
|
|
144
|
+
## What Schedule Core is not
|
|
145
|
+
|
|
146
|
+
Schedule Core does not:
|
|
147
|
+
|
|
148
|
+
- render a Gantt chart or React component;
|
|
149
|
+
- own a browser application's component state;
|
|
150
|
+
- fetch schedule data or make HTTP requests;
|
|
151
|
+
- write to a database or storage service;
|
|
152
|
+
- decide how warnings, analytics, or rejected commands are presented.
|
|
153
|
+
|
|
154
|
+
It does track dirty entities and persistence checkpoints, but the consumer performs the actual save.
|
|
155
|
+
|
|
156
|
+
## Repository map
|
|
157
|
+
|
|
158
|
+
```text
|
|
159
|
+
src/
|
|
160
|
+
├── index.ts public package contract
|
|
161
|
+
├── init/ facade, initialization, read API
|
|
162
|
+
├── dispatch/ commands, handlers, ChangeSets, undo/redo
|
|
163
|
+
├── internal/ state, hierarchy, ordering, dependency graph
|
|
164
|
+
├── autoscheduler/ ASAP/ALAP scheduling and link propagation
|
|
165
|
+
├── calendar/ working-time API and engine adapter
|
|
166
|
+
├── columns/ typed field mutation pipelines
|
|
167
|
+
├── propagations/ parent and derived-field propagation
|
|
168
|
+
├── critical-path/ critical-path facade and legacy adapter
|
|
169
|
+
├── constraints/ constraint vocabulary and date semantics
|
|
170
|
+
├── boundary/ backend normalization and save tracking
|
|
171
|
+
└── testing/ fixtures, scenarios, recordings, and parity harnesses
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
## Testing
|
|
175
|
+
|
|
176
|
+
[Vitest](https://vitest.dev/) runs two explicit projects:
|
|
46
177
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
boundary, and persist them at the storage boundary.
|
|
178
|
+
- **Unit** — sibling tests for domain modules, mutation pipelines, calendars, scheduling, graph rules, history, and architecture gates.
|
|
179
|
+
- **Integration** — parity suites and recorded sessions over captured project data.
|
|
50
180
|
|
|
51
|
-
|
|
52
|
-
|
|
181
|
+
The repository also contains Gherkin behavior scenarios, production-derived recordings, undo/redo corpus checks, large-project regression cases, and compile-time boundary tests. These are verification strategies, not a published coverage or benchmark claim.
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
npm test # all Vitest projects
|
|
185
|
+
npm run test:unit # unit project
|
|
186
|
+
npm run test:integration # parity and session replays
|
|
187
|
+
```
|
|
53
188
|
|
|
54
189
|
## Development
|
|
55
190
|
|
|
191
|
+
Requires Node.js 20 or newer.
|
|
192
|
+
|
|
56
193
|
```bash
|
|
57
194
|
npm ci
|
|
58
195
|
npm run typecheck
|
|
196
|
+
npm run typecheck:boundary
|
|
197
|
+
npm run lint
|
|
59
198
|
npm test
|
|
60
199
|
npm run build
|
|
61
200
|
```
|
|
62
201
|
|
|
63
|
-
The build
|
|
64
|
-
|
|
202
|
+
The build emits ESM, CommonJS, type declarations, source maps, and a browser IIFE under `dist/`. The package declares no runtime dependencies.
|
|
203
|
+
|
|
204
|
+
## Documentation
|
|
205
|
+
|
|
206
|
+
- [Public API](docs/API.md) — supported entry point, lifecycle, commands, reads, persistence, and types.
|
|
207
|
+
- [Model invariants](INVARIANTS.md) — verified units, dates, queueing, write capture, persistence, and graph rules.
|
|
208
|
+
- [Domain and architecture index](docs/domain/README.md) — canonical map of the detailed domain documentation.
|
|
209
|
+
- [State roles](docs/domain/STATE_ROLES.md) — internal capability boundaries around `ScheduleState`.
|
|
210
|
+
- [Activity ownership](docs/domain/model/SCHEDULE_CORE_OWNERSHIP.md) — current core/render authority by field category.
|
|
211
|
+
- [Temporal model](docs/domain/scheduling/temporal-model.md) — temporal vocabulary, policies, and known open decisions.
|
|
212
|
+
- [Calendars](docs/domain/dates-calendars/CALENDARS.md) — working-time model, normalization, and engine boundary.
|
|
213
|
+
- [Constraints](docs/domain/constraints/01-constraint-types-catalog.md) — supported constraint vocabulary and semantics.
|
|
214
|
+
- [Architecture audit](docs/audit/README.md) — measured implementation map, findings, and unresolved questions.
|
|
215
|
+
- [Changelog](CHANGELOG.md) — released behavior and package history.
|