@spottoai/types-package 1.0.2-beta.420 → 1.0.2-beta.421

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.
Files changed (77) hide show
  1. package/README.md +3 -0
  2. package/dist/accounts/azureSpSetup.d.ts +5 -0
  3. package/dist/accounts/azureSpSetup.d.ts.map +1 -1
  4. package/dist/accounts/azureSpSetup.js.map +1 -1
  5. package/dist/accounts/writePermissions.d.ts +5 -1
  6. package/dist/accounts/writePermissions.d.ts.map +1 -1
  7. package/dist/accounts/writePermissions.js +9 -0
  8. package/dist/accounts/writePermissions.js.map +1 -1
  9. package/dist/esm/accounts/writePermissions.js +9 -0
  10. package/dist/esm/scheduler/index.js +2 -3
  11. package/dist/esm/scheduler/resourceStrategy.js +2 -0
  12. package/dist/esm/scheduler/resourceStrategyCapabilityValidation.js +241 -0
  13. package/dist/esm/scheduler/resourceStrategyContracts.js +14 -0
  14. package/dist/esm/scheduler/resourceStrategyFinancialValidation.js +145 -0
  15. package/dist/esm/scheduler/resourceStrategyPermissionValidation.js +190 -0
  16. package/dist/esm/scheduler/resourceStrategyScheduleValidation.js +332 -0
  17. package/dist/esm/scheduler/resourceStrategyValidation.js +4 -0
  18. package/dist/esm/scheduler/resourceStrategyValidationShared.js +261 -0
  19. package/dist/esm/scheduler/weeklyAvailabilityFixtures.js +140 -0
  20. package/dist/scheduler/index.d.ts +2 -3
  21. package/dist/scheduler/index.d.ts.map +1 -1
  22. package/dist/scheduler/index.js +2 -3
  23. package/dist/scheduler/index.js.map +1 -1
  24. package/dist/scheduler/resourceStrategy.d.ts +3 -0
  25. package/dist/scheduler/resourceStrategy.d.ts.map +1 -0
  26. package/dist/scheduler/resourceStrategy.js +19 -0
  27. package/dist/scheduler/resourceStrategy.js.map +1 -0
  28. package/dist/scheduler/resourceStrategyCapabilityValidation.d.ts +4 -0
  29. package/dist/scheduler/resourceStrategyCapabilityValidation.d.ts.map +1 -0
  30. package/dist/scheduler/resourceStrategyCapabilityValidation.js +246 -0
  31. package/dist/scheduler/resourceStrategyCapabilityValidation.js.map +1 -0
  32. package/dist/scheduler/resourceStrategyContracts.d.ts +412 -0
  33. package/dist/scheduler/resourceStrategyContracts.d.ts.map +1 -0
  34. package/dist/scheduler/resourceStrategyContracts.js +18 -0
  35. package/dist/scheduler/resourceStrategyContracts.js.map +1 -0
  36. package/dist/scheduler/resourceStrategyFinancialValidation.d.ts +5 -0
  37. package/dist/scheduler/resourceStrategyFinancialValidation.d.ts.map +1 -0
  38. package/dist/scheduler/resourceStrategyFinancialValidation.js +151 -0
  39. package/dist/scheduler/resourceStrategyFinancialValidation.js.map +1 -0
  40. package/dist/scheduler/resourceStrategyPermissionValidation.d.ts +4 -0
  41. package/dist/scheduler/resourceStrategyPermissionValidation.d.ts.map +1 -0
  42. package/dist/scheduler/resourceStrategyPermissionValidation.js +195 -0
  43. package/dist/scheduler/resourceStrategyPermissionValidation.js.map +1 -0
  44. package/dist/scheduler/resourceStrategyScheduleValidation.d.ts +10 -0
  45. package/dist/scheduler/resourceStrategyScheduleValidation.d.ts.map +1 -0
  46. package/dist/scheduler/resourceStrategyScheduleValidation.js +343 -0
  47. package/dist/scheduler/resourceStrategyScheduleValidation.js.map +1 -0
  48. package/dist/scheduler/resourceStrategyValidation.d.ts +5 -0
  49. package/dist/scheduler/resourceStrategyValidation.d.ts.map +1 -0
  50. package/dist/scheduler/resourceStrategyValidation.js +21 -0
  51. package/dist/scheduler/resourceStrategyValidation.js.map +1 -0
  52. package/dist/scheduler/resourceStrategyValidationShared.d.ts +19 -0
  53. package/dist/scheduler/resourceStrategyValidationShared.d.ts.map +1 -0
  54. package/dist/scheduler/resourceStrategyValidationShared.js +281 -0
  55. package/dist/scheduler/resourceStrategyValidationShared.js.map +1 -0
  56. package/dist/scheduler/scheduler.d.ts +6 -159
  57. package/dist/scheduler/scheduler.d.ts.map +1 -1
  58. package/dist/scheduler/weeklyAvailabilityFixtures.d.ts +26 -0
  59. package/dist/scheduler/weeklyAvailabilityFixtures.d.ts.map +1 -0
  60. package/dist/scheduler/weeklyAvailabilityFixtures.js +144 -0
  61. package/dist/scheduler/weeklyAvailabilityFixtures.js.map +1 -0
  62. package/package.json +11 -3
  63. package/dist/esm/scheduler/bastionSchedule.js +0 -1
  64. package/dist/esm/scheduler/bastionScheduleProfile.js +0 -206
  65. package/dist/esm/scheduler/bastionScheduleValidation.js +0 -401
  66. package/dist/scheduler/bastionSchedule.d.ts +0 -113
  67. package/dist/scheduler/bastionSchedule.d.ts.map +0 -1
  68. package/dist/scheduler/bastionSchedule.js +0 -3
  69. package/dist/scheduler/bastionSchedule.js.map +0 -1
  70. package/dist/scheduler/bastionScheduleProfile.d.ts +0 -24
  71. package/dist/scheduler/bastionScheduleProfile.d.ts.map +0 -1
  72. package/dist/scheduler/bastionScheduleProfile.js +0 -210
  73. package/dist/scheduler/bastionScheduleProfile.js.map +0 -1
  74. package/dist/scheduler/bastionScheduleValidation.d.ts +0 -10
  75. package/dist/scheduler/bastionScheduleValidation.d.ts.map +0 -1
  76. package/dist/scheduler/bastionScheduleValidation.js +0 -412
  77. package/dist/scheduler/bastionScheduleValidation.js.map +0 -1
@@ -0,0 +1,261 @@
1
+ import { RESOURCE_STRATEGY_CONTRACT_LIMITS } from './resourceStrategyContracts.js';
2
+ const FORBIDDEN_AUTHORING_KEYS = new Set([
3
+ '__proto__',
4
+ 'prototype',
5
+ 'constructor',
6
+ 'actionId',
7
+ 'actionRef',
8
+ 'actionDefinitionId',
9
+ 'actionDefinitionRef',
10
+ 'workflowRef',
11
+ 'operation',
12
+ 'providerOperation',
13
+ 'compiledOperation',
14
+ 'httpMethod',
15
+ 'endpoint',
16
+ 'apiVersion',
17
+ 'requestTemplate',
18
+ 'permissions',
19
+ 'permissionActions',
20
+ 'permissionSetRef',
21
+ 'permissionSetRefs',
22
+ 'baseline',
23
+ 'baselineRef',
24
+ 'selectorRef',
25
+ 'restoreBaseline',
26
+ 'compiledDueRow',
27
+ ]);
28
+ const INHERITED_FORBIDDEN_AUTHORING_KEYS = [...FORBIDDEN_AUTHORING_KEYS].filter(key => key !== '__proto__' && key !== 'prototype' && key !== 'constructor');
29
+ export function isRecord(value) {
30
+ if (value === null || typeof value !== 'object' || Array.isArray(value))
31
+ return false;
32
+ try {
33
+ const prototype = Object.getPrototypeOf(value);
34
+ if (prototype !== Object.prototype && prototype !== null)
35
+ return false;
36
+ return Reflect.ownKeys(value).every(key => {
37
+ if (typeof key !== 'string')
38
+ return false;
39
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
40
+ return descriptor !== undefined && descriptor.enumerable && 'value' in descriptor;
41
+ });
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ }
47
+ export function hasOnlyKeys(value, allowed) {
48
+ try {
49
+ const allowedSet = new Set(allowed);
50
+ return (Object.keys(value).every(key => allowedSet.has(key)) &&
51
+ allowed.every(key => !Reflect.has(value, key) || Object.prototype.hasOwnProperty.call(value, key)));
52
+ }
53
+ catch {
54
+ return false;
55
+ }
56
+ }
57
+ export function isBoundedString(value, maximum = RESOURCE_STRATEGY_CONTRACT_LIMITS.textLength) {
58
+ return typeof value === 'string' && value.length > 0 && value.length <= maximum;
59
+ }
60
+ export function isOptionalBoundedString(value, maximum = RESOURCE_STRATEGY_CONTRACT_LIMITS.textLength) {
61
+ return value === undefined || isBoundedString(value, maximum);
62
+ }
63
+ export function isPositiveInteger(value) {
64
+ return typeof value === 'number' && Number.isSafeInteger(value) && value > 0;
65
+ }
66
+ export function isNonNegativeInteger(value) {
67
+ return typeof value === 'number' && Number.isSafeInteger(value) && value >= 0;
68
+ }
69
+ export function isIsoTimestamp(value) {
70
+ if (typeof value !== 'string' || !/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d{3})?Z$/.test(value))
71
+ return false;
72
+ const instant = new Date(value);
73
+ if (!Number.isFinite(instant.getTime()))
74
+ return false;
75
+ const canonical = instant.toISOString();
76
+ return value.includes('.') ? canonical === value : canonical.replace('.000Z', 'Z') === value;
77
+ }
78
+ export function isDate(value) {
79
+ if (typeof value !== 'string' || !/^\d{4}-\d{2}-\d{2}$/.test(value))
80
+ return false;
81
+ const date = new Date(`${value}T00:00:00.000Z`);
82
+ return Number.isFinite(date.getTime()) && date.toISOString().slice(0, 10) === value;
83
+ }
84
+ export function isTime(value) {
85
+ return typeof value === 'string' && /^(?:[01]\d|2[0-3]):[0-5]\d$/.test(value);
86
+ }
87
+ export function isCurrency(value) {
88
+ return typeof value === 'string' && /^[A-Z]{3}$/.test(value);
89
+ }
90
+ export function isNonNegativeDecimal(value) {
91
+ return typeof value === 'string' && /^\d{1,15}(?:\.\d{1,8})?$/.test(value);
92
+ }
93
+ export function isIanaTimezone(value) {
94
+ if (!isBoundedString(value, 100))
95
+ return false;
96
+ try {
97
+ new Intl.DateTimeFormat('en-US', { timeZone: value }).format(0);
98
+ return true;
99
+ }
100
+ catch {
101
+ return false;
102
+ }
103
+ }
104
+ function jsonStringByteLengthWithin(value, maximum) {
105
+ let bytes = 2;
106
+ for (let index = 0; index < value.length; index += 1) {
107
+ const codeUnit = value.charCodeAt(index);
108
+ if (codeUnit === 0x22 ||
109
+ codeUnit === 0x5c ||
110
+ codeUnit === 0x08 ||
111
+ codeUnit === 0x09 ||
112
+ codeUnit === 0x0a ||
113
+ codeUnit === 0x0c ||
114
+ codeUnit === 0x0d) {
115
+ bytes += 2;
116
+ }
117
+ else if (codeUnit <= 0x1f ||
118
+ (codeUnit >= 0xd800 &&
119
+ codeUnit <= 0xdfff &&
120
+ !(codeUnit <= 0xdbff && index + 1 < value.length && value.charCodeAt(index + 1) >= 0xdc00 && value.charCodeAt(index + 1) <= 0xdfff))) {
121
+ bytes += 6;
122
+ }
123
+ else if (codeUnit <= 0x7f) {
124
+ bytes += 1;
125
+ }
126
+ else if (codeUnit <= 0x7ff) {
127
+ bytes += 2;
128
+ }
129
+ else if (codeUnit <= 0xdbff) {
130
+ bytes += 4;
131
+ index += 1;
132
+ }
133
+ else {
134
+ bytes += 3;
135
+ }
136
+ if (bytes > maximum)
137
+ return null;
138
+ }
139
+ return bytes;
140
+ }
141
+ export function isWithinJsonByteLimit(value, maximum) {
142
+ if (!Number.isSafeInteger(maximum) || maximum < 0)
143
+ return false;
144
+ const stack = [value];
145
+ let bytes = 0;
146
+ let nodes = 0;
147
+ try {
148
+ while (stack.length > 0) {
149
+ nodes += 1;
150
+ if (nodes > 10000)
151
+ return false;
152
+ const current = stack.pop();
153
+ if (current === null) {
154
+ bytes += 4;
155
+ }
156
+ else if (typeof current === 'string') {
157
+ const stringBytes = jsonStringByteLengthWithin(current, maximum - bytes);
158
+ if (stringBytes === null)
159
+ return false;
160
+ bytes += stringBytes;
161
+ }
162
+ else if (typeof current === 'number') {
163
+ if (!Number.isFinite(current))
164
+ return false;
165
+ bytes += String(Object.is(current, -0) ? 0 : current).length;
166
+ }
167
+ else if (typeof current === 'boolean') {
168
+ bytes += current ? 4 : 5;
169
+ }
170
+ else if (Array.isArray(current)) {
171
+ if (Object.getPrototypeOf(current) !== Array.prototype)
172
+ return false;
173
+ bytes += 2 + Math.max(0, current.length - 1);
174
+ if (bytes > maximum)
175
+ return false;
176
+ const ownKeys = Reflect.ownKeys(current);
177
+ if (ownKeys.length !== current.length + 1 || !ownKeys.includes('length'))
178
+ return false;
179
+ for (let index = 0; index < current.length; index += 1) {
180
+ const descriptor = Object.getOwnPropertyDescriptor(current, String(index));
181
+ if (descriptor === undefined || !descriptor.enumerable || !('value' in descriptor))
182
+ return false;
183
+ stack.push(descriptor.value);
184
+ }
185
+ }
186
+ else if (isRecord(current)) {
187
+ const keys = Object.keys(current);
188
+ bytes += 2 + Math.max(0, keys.length - 1);
189
+ if (bytes > maximum)
190
+ return false;
191
+ for (const key of keys) {
192
+ const keyBytes = jsonStringByteLengthWithin(key, maximum - bytes);
193
+ if (keyBytes === null)
194
+ return false;
195
+ bytes += keyBytes + 1;
196
+ if (bytes > maximum)
197
+ return false;
198
+ const descriptor = Object.getOwnPropertyDescriptor(current, key);
199
+ if (descriptor === undefined || !('value' in descriptor))
200
+ return false;
201
+ stack.push(descriptor.value);
202
+ }
203
+ }
204
+ else {
205
+ return false;
206
+ }
207
+ if (bytes > maximum)
208
+ return false;
209
+ }
210
+ return true;
211
+ }
212
+ catch {
213
+ return false;
214
+ }
215
+ }
216
+ export function isBoundedStringArray(value, maximum = RESOURCE_STRATEGY_CONTRACT_LIMITS.metadataItems) {
217
+ return Array.isArray(value) && value.length <= maximum && value.every(item => isBoundedString(item, 2000));
218
+ }
219
+ export function containsForbiddenKey(value, depth = 0) {
220
+ try {
221
+ if (depth > 8)
222
+ return true;
223
+ if (value !== null && typeof value === 'object') {
224
+ if (INHERITED_FORBIDDEN_AUTHORING_KEYS.some(key => Reflect.has(value, key) && !Object.prototype.hasOwnProperty.call(value, key))) {
225
+ return true;
226
+ }
227
+ }
228
+ if (Array.isArray(value))
229
+ return value.some(item => containsForbiddenKey(item, depth + 1));
230
+ if (!isRecord(value))
231
+ return false;
232
+ return Object.keys(value).some(key => FORBIDDEN_AUTHORING_KEYS.has(key) || containsForbiddenKey(value[key], depth + 1));
233
+ }
234
+ catch {
235
+ return true;
236
+ }
237
+ }
238
+ function isBoundedJsonValue(value, depth = 0) {
239
+ if (depth > 8)
240
+ return false;
241
+ if (value === null || typeof value === 'boolean' || typeof value === 'string')
242
+ return true;
243
+ if (typeof value === 'number')
244
+ return Number.isFinite(value);
245
+ if (Array.isArray(value))
246
+ return value.length <= 128 && value.every(item => isBoundedJsonValue(item, depth + 1));
247
+ if (!isRecord(value) || Object.keys(value).length > 128)
248
+ return false;
249
+ return Object.entries(value).every(([key, item]) => !FORBIDDEN_AUTHORING_KEYS.has(key) && isBoundedJsonValue(item, depth + 1));
250
+ }
251
+ export function isBoundedParameters(value) {
252
+ if (!isWithinJsonByteLimit(value, RESOURCE_STRATEGY_CONTRACT_LIMITS.parameterBytes))
253
+ return false;
254
+ return isRecord(value) && isBoundedJsonValue(value) && !containsForbiddenKey(value);
255
+ }
256
+ export function isCapabilityRef(value) {
257
+ return (isRecord(value) &&
258
+ hasOnlyKeys(value, ['capabilityId', 'capabilityVersion']) &&
259
+ isBoundedString(value.capabilityId, 200) &&
260
+ isPositiveInteger(value.capabilityVersion));
261
+ }
@@ -0,0 +1,140 @@
1
+ const rule = (ruleId, daysOfWeek, desiredStateAtLocal, transition) => ({ ruleId, daysOfWeek, desiredStateAtLocal, transition });
2
+ const fixtures = [
3
+ {
4
+ caseId: 'business-hours',
5
+ timezone: 'Pacific/Auckland',
6
+ validity: 'valid',
7
+ periods: [1, 2, 3, 4, 5].map(day => ({
8
+ periodKey: `weekday-${day}`,
9
+ start: { dayOfWeek: day, timeLocal: '08:00' },
10
+ end: { dayOfWeek: day, timeLocal: '18:00' },
11
+ })),
12
+ expectedRules: [rule('weekday-restore', [1, 2, 3, 4, 5], '08:00', 'restore'), rule('weekday-reduce', [1, 2, 3, 4, 5], '18:00', 'reduce')],
13
+ stateSamples: [
14
+ { instantUtc: '2026-09-13T19:59:59.999Z', expectedState: 'reduced' },
15
+ { instantUtc: '2026-09-13T20:00:00.000Z', expectedState: 'normal' },
16
+ { instantUtc: '2026-09-14T06:00:00.000Z', expectedState: 'reduced' },
17
+ ],
18
+ },
19
+ {
20
+ caseId: 'daily',
21
+ timezone: 'Pacific/Auckland',
22
+ validity: 'valid',
23
+ periods: [0, 1, 2, 3, 4, 5, 6].map(day => ({
24
+ periodKey: `day-${day}`,
25
+ start: { dayOfWeek: day, timeLocal: '08:00' },
26
+ end: { dayOfWeek: day, timeLocal: '18:00' },
27
+ })),
28
+ expectedRules: [rule('daily-restore', [0, 1, 2, 3, 4, 5, 6], '08:00', 'restore'), rule('daily-reduce', [0, 1, 2, 3, 4, 5, 6], '18:00', 'reduce')],
29
+ stateSamples: [
30
+ { instantUtc: '2026-09-13T19:59:59.999Z', expectedState: 'reduced' },
31
+ { instantUtc: '2026-09-13T20:00:00.000Z', expectedState: 'normal' },
32
+ { instantUtc: '2026-09-14T06:00:00.000Z', expectedState: 'reduced' },
33
+ ],
34
+ },
35
+ {
36
+ caseId: 'cross-midnight',
37
+ timezone: 'Pacific/Auckland',
38
+ validity: 'valid',
39
+ periods: [{ periodKey: 'overnight', start: { dayOfWeek: 5, timeLocal: '22:00' }, end: { dayOfWeek: 6, timeLocal: '02:00' } }],
40
+ expectedRules: [rule('overnight-restore', [5], '22:00', 'restore'), rule('overnight-reduce', [6], '02:00', 'reduce')],
41
+ stateSamples: [
42
+ { instantUtc: '2026-09-18T09:59:59.999Z', expectedState: 'reduced' },
43
+ { instantUtc: '2026-09-18T10:00:00.000Z', expectedState: 'normal' },
44
+ { instantUtc: '2026-09-18T14:00:00.000Z', expectedState: 'reduced' },
45
+ ],
46
+ },
47
+ {
48
+ caseId: 'week-wrap',
49
+ timezone: 'Pacific/Auckland',
50
+ validity: 'valid',
51
+ periods: [{ periodKey: 'week-wrap', start: { dayOfWeek: 0, timeLocal: '22:00' }, end: { dayOfWeek: 1, timeLocal: '02:00' } }],
52
+ expectedRules: [rule('week-wrap-restore', [0], '22:00', 'restore'), rule('week-wrap-reduce', [1], '02:00', 'reduce')],
53
+ stateSamples: [
54
+ { instantUtc: '2026-09-20T09:59:59.999Z', expectedState: 'reduced' },
55
+ { instantUtc: '2026-09-20T10:00:00.000Z', expectedState: 'normal' },
56
+ { instantUtc: '2026-09-20T14:00:00.000Z', expectedState: 'reduced' },
57
+ ],
58
+ },
59
+ {
60
+ caseId: 'touching-periods',
61
+ timezone: 'UTC',
62
+ validity: 'valid',
63
+ periods: [
64
+ { periodKey: 'morning', start: { dayOfWeek: 1, timeLocal: '08:00' }, end: { dayOfWeek: 1, timeLocal: '12:00' } },
65
+ { periodKey: 'afternoon', start: { dayOfWeek: 1, timeLocal: '12:00' }, end: { dayOfWeek: 1, timeLocal: '18:00' } },
66
+ ],
67
+ expectedRules: [rule('touching-restore', [1], '08:00', 'restore'), rule('touching-reduce', [1], '18:00', 'reduce')],
68
+ stateSamples: [
69
+ { instantUtc: '2026-09-14T07:59:59.999Z', expectedState: 'reduced' },
70
+ { instantUtc: '2026-09-14T08:00:00.000Z', expectedState: 'normal' },
71
+ { instantUtc: '2026-09-14T12:00:00.000Z', expectedState: 'normal' },
72
+ { instantUtc: '2026-09-14T18:00:00.000Z', expectedState: 'reduced' },
73
+ ],
74
+ },
75
+ {
76
+ caseId: 'exact-boundaries',
77
+ timezone: 'UTC',
78
+ validity: 'valid',
79
+ periods: [{ periodKey: 'window', start: { dayOfWeek: 1, timeLocal: '08:00' }, end: { dayOfWeek: 1, timeLocal: '18:00' } }],
80
+ expectedRules: [rule('window-restore', [1], '08:00', 'restore'), rule('window-reduce', [1], '18:00', 'reduce')],
81
+ stateSamples: [
82
+ { instantUtc: '2026-09-14T07:59:59.999Z', expectedState: 'reduced' },
83
+ { instantUtc: '2026-09-14T08:00:00.000Z', expectedState: 'normal' },
84
+ { instantUtc: '2026-09-14T18:00:00.000Z', expectedState: 'reduced' },
85
+ ],
86
+ },
87
+ {
88
+ caseId: 'spring-forward-gap',
89
+ timezone: 'Pacific/Auckland',
90
+ validity: 'valid',
91
+ periods: [{ periodKey: 'gap', start: { dayOfWeek: 0, timeLocal: '02:30' }, end: { dayOfWeek: 0, timeLocal: '04:00' } }],
92
+ expectedRules: [rule('gap-restore', [0], '02:30', 'restore'), rule('gap-reduce', [0], '04:00', 'reduce')],
93
+ stateSamples: [{ instantUtc: '2026-09-26T14:00:00.000Z', expectedState: 'normal' }],
94
+ dstPolicy: 'spring-forward-first-valid',
95
+ },
96
+ {
97
+ caseId: 'fall-back-restore-first',
98
+ timezone: 'Pacific/Auckland',
99
+ validity: 'valid',
100
+ periods: [{ periodKey: 'overlap-start', start: { dayOfWeek: 0, timeLocal: '02:30' }, end: { dayOfWeek: 0, timeLocal: '04:00' } }],
101
+ expectedRules: [rule('overlap-start-restore', [0], '02:30', 'restore'), rule('overlap-start-reduce', [0], '04:00', 'reduce')],
102
+ stateSamples: [{ instantUtc: '2026-04-04T13:30:00.000Z', expectedState: 'normal' }],
103
+ dstPolicy: 'fall-back-restore-first',
104
+ },
105
+ {
106
+ caseId: 'fall-back-reduce-second',
107
+ timezone: 'Pacific/Auckland',
108
+ validity: 'valid',
109
+ periods: [{ periodKey: 'overlap-end', start: { dayOfWeek: 0, timeLocal: '00:30' }, end: { dayOfWeek: 0, timeLocal: '02:30' } }],
110
+ expectedRules: [rule('overlap-end-restore', [0], '00:30', 'restore'), rule('overlap-end-reduce', [0], '02:30', 'reduce')],
111
+ stateSamples: [{ instantUtc: '2026-04-04T14:30:00.000Z', expectedState: 'reduced' }],
112
+ dstPolicy: 'fall-back-reduce-second',
113
+ },
114
+ {
115
+ caseId: 'invalid-overlap',
116
+ timezone: 'UTC',
117
+ validity: 'invalid',
118
+ periods: [
119
+ { periodKey: 'first', start: { dayOfWeek: 1, timeLocal: '08:00' }, end: { dayOfWeek: 1, timeLocal: '12:00' } },
120
+ { periodKey: 'second', start: { dayOfWeek: 1, timeLocal: '11:00' }, end: { dayOfWeek: 1, timeLocal: '13:00' } },
121
+ ],
122
+ invalidReason: 'overlap',
123
+ },
124
+ {
125
+ caseId: 'invalid-conflicting-transition',
126
+ timezone: 'UTC',
127
+ validity: 'invalid',
128
+ periods: [{ periodKey: 'zero-duration', start: { dayOfWeek: 1, timeLocal: '08:00' }, end: { dayOfWeek: 1, timeLocal: '08:00' } }],
129
+ invalidReason: 'conflicting-transition',
130
+ },
131
+ ];
132
+ function deepFreeze(value) {
133
+ if (value !== null && typeof value === 'object' && !Object.isFrozen(value)) {
134
+ for (const nestedValue of Object.values(value))
135
+ deepFreeze(nestedValue);
136
+ Object.freeze(value);
137
+ }
138
+ return value;
139
+ }
140
+ export const WEEKLY_AVAILABILITY_FIXTURES_V1 = deepFreeze(fixtures);
@@ -1,5 +1,4 @@
1
- export * from './bastionSchedule';
2
- export * from './bastionScheduleProfile';
3
- export * from './bastionScheduleValidation';
4
1
  export * from './scheduler';
2
+ export * from './resourceStrategy';
3
+ export * from './weeklyAvailabilityFixtures';
5
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scheduler/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAC;AAClC,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,aAAa,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/scheduler/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,oBAAoB,CAAC;AACnC,cAAc,8BAA8B,CAAC"}
@@ -14,8 +14,7 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
14
  for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
15
  };
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
- __exportStar(require("./bastionSchedule"), exports);
18
- __exportStar(require("./bastionScheduleProfile"), exports);
19
- __exportStar(require("./bastionScheduleValidation"), exports);
20
17
  __exportStar(require("./scheduler"), exports);
18
+ __exportStar(require("./resourceStrategy"), exports);
19
+ __exportStar(require("./weeklyAvailabilityFixtures"), exports);
21
20
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scheduler/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,oDAAkC;AAClC,2DAAyC;AACzC,8DAA4C;AAC5C,8CAA4B"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/scheduler/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8CAA4B;AAC5B,qDAAmC;AACnC,+DAA6C"}
@@ -0,0 +1,3 @@
1
+ export * from './resourceStrategyContracts';
2
+ export * from './resourceStrategyValidation';
3
+ //# sourceMappingURL=resourceStrategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceStrategy.d.ts","sourceRoot":"","sources":["../../src/scheduler/resourceStrategy.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./resourceStrategyContracts"), exports);
18
+ __exportStar(require("./resourceStrategyValidation"), exports);
19
+ //# sourceMappingURL=resourceStrategy.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceStrategy.js","sourceRoot":"","sources":["../../src/scheduler/resourceStrategy.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,8DAA4C;AAC5C,+DAA6C"}
@@ -0,0 +1,4 @@
1
+ import { type ResourceSchedulingCapabilityProjection, type ResourceSchedulingReadinessProjection } from './resourceStrategyContracts';
2
+ export declare function isResourceSchedulingCapabilityProjection(value: unknown): value is ResourceSchedulingCapabilityProjection;
3
+ export declare function isResourceSchedulingReadinessProjection(value: unknown): value is ResourceSchedulingReadinessProjection;
4
+ //# sourceMappingURL=resourceStrategyCapabilityValidation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resourceStrategyCapabilityValidation.d.ts","sourceRoot":"","sources":["../../src/scheduler/resourceStrategyCapabilityValidation.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,KAAK,sCAAsC,EAC3C,KAAK,qCAAqC,EAE3C,MAAM,6BAA6B,CAAC;AAerC,wBAAgB,wCAAwC,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,sCAAsC,CA8MxH;AAkBD,wBAAgB,uCAAuC,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,qCAAqC,CAmCtH"}