@mrtdown/core 2.0.0-alpha.5 → 2.0.0-alpha.7

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 (252) hide show
  1. package/dist/index.d.ts +0 -7
  2. package/dist/index.js +0 -7
  3. package/dist/index.js.map +1 -1
  4. package/dist/schema/Landmark.js.map +1 -1
  5. package/dist/schema/Line.d.ts +6 -0
  6. package/dist/schema/Line.js +2 -1
  7. package/dist/schema/Line.js.map +1 -1
  8. package/dist/schema/Operator.js.map +1 -1
  9. package/dist/schema/Service.js.map +1 -1
  10. package/dist/schema/Station.js.map +1 -1
  11. package/dist/schema/Town.js.map +1 -1
  12. package/dist/schema/common.js.map +1 -1
  13. package/dist/schema/issue/bundle.js.map +1 -1
  14. package/dist/schema/issue/cause.js.map +1 -1
  15. package/dist/schema/issue/claim.js.map +1 -1
  16. package/dist/schema/issue/entity.js.map +1 -1
  17. package/dist/schema/issue/evidence.js.map +1 -1
  18. package/dist/schema/issue/facilityEffect.js.map +1 -1
  19. package/dist/schema/issue/id.js.map +1 -1
  20. package/dist/schema/issue/impactEvent.js.map +1 -1
  21. package/dist/schema/issue/issue.js.map +1 -1
  22. package/dist/schema/issue/issueType.js.map +1 -1
  23. package/dist/schema/issue/period.js.map +1 -1
  24. package/dist/schema/issue/serviceEffect.js.map +1 -1
  25. package/dist/schema/issue/serviceScope.js.map +1 -1
  26. package/package.json +19 -44
  27. package/README.md +0 -107
  28. package/dist/cli/commands/create.d.ts +0 -30
  29. package/dist/cli/commands/create.js +0 -189
  30. package/dist/cli/commands/create.js.map +0 -1
  31. package/dist/cli/commands/list.d.ts +0 -6
  32. package/dist/cli/commands/list.js +0 -106
  33. package/dist/cli/commands/list.js.map +0 -1
  34. package/dist/cli/commands/show.d.ts +0 -6
  35. package/dist/cli/commands/show.js +0 -156
  36. package/dist/cli/commands/show.js.map +0 -1
  37. package/dist/cli/commands/validate.d.ts +0 -6
  38. package/dist/cli/commands/validate.js +0 -19
  39. package/dist/cli/commands/validate.js.map +0 -1
  40. package/dist/cli/index.d.ts +0 -2
  41. package/dist/cli/index.js +0 -162
  42. package/dist/cli/index.js.map +0 -1
  43. package/dist/constants.d.ts +0 -10
  44. package/dist/constants.js +0 -11
  45. package/dist/constants.js.map +0 -1
  46. package/dist/helpers/calculateDurationWithinServiceHours.d.ts +0 -2
  47. package/dist/helpers/calculateDurationWithinServiceHours.js +0 -13
  48. package/dist/helpers/calculateDurationWithinServiceHours.js.map +0 -1
  49. package/dist/helpers/calculateDurationWithinServiceHours.test.d.ts +0 -1
  50. package/dist/helpers/calculateDurationWithinServiceHours.test.js +0 -83
  51. package/dist/helpers/calculateDurationWithinServiceHours.test.js.map +0 -1
  52. package/dist/helpers/computeImpactFromEvidenceClaims.d.ts +0 -21
  53. package/dist/helpers/computeImpactFromEvidenceClaims.js +0 -293
  54. package/dist/helpers/computeImpactFromEvidenceClaims.js.map +0 -1
  55. package/dist/helpers/computeImpactFromEvidenceClaims.test.d.ts +0 -1
  56. package/dist/helpers/computeImpactFromEvidenceClaims.test.js +0 -544
  57. package/dist/helpers/computeImpactFromEvidenceClaims.test.js.map +0 -1
  58. package/dist/helpers/computeStartOfDaysWithinInterval.d.ts +0 -2
  59. package/dist/helpers/computeStartOfDaysWithinInterval.js +0 -15
  60. package/dist/helpers/computeStartOfDaysWithinInterval.js.map +0 -1
  61. package/dist/helpers/computeStartOfDaysWithinInterval.test.d.ts +0 -1
  62. package/dist/helpers/computeStartOfDaysWithinInterval.test.js +0 -126
  63. package/dist/helpers/computeStartOfDaysWithinInterval.test.js.map +0 -1
  64. package/dist/helpers/estimateOpenAICost.d.ts +0 -40
  65. package/dist/helpers/estimateOpenAICost.js +0 -55
  66. package/dist/helpers/estimateOpenAICost.js.map +0 -1
  67. package/dist/helpers/keyForAffectedEntity.d.ts +0 -7
  68. package/dist/helpers/keyForAffectedEntity.js +0 -14
  69. package/dist/helpers/keyForAffectedEntity.js.map +0 -1
  70. package/dist/helpers/normalizeRecurringPeriod.d.ts +0 -7
  71. package/dist/helpers/normalizeRecurringPeriod.js +0 -118
  72. package/dist/helpers/normalizeRecurringPeriod.js.map +0 -1
  73. package/dist/helpers/normalizeRecurringPeriod.test.d.ts +0 -1
  74. package/dist/helpers/normalizeRecurringPeriod.test.js +0 -93
  75. package/dist/helpers/normalizeRecurringPeriod.test.js.map +0 -1
  76. package/dist/helpers/resolvePeriods.d.ts +0 -224
  77. package/dist/helpers/resolvePeriods.js +0 -207
  78. package/dist/helpers/resolvePeriods.js.map +0 -1
  79. package/dist/helpers/resolvePeriods.test.d.ts +0 -1
  80. package/dist/helpers/resolvePeriods.test.js +0 -239
  81. package/dist/helpers/resolvePeriods.test.js.map +0 -1
  82. package/dist/helpers/splitIntervalByServiceHours.d.ts +0 -2
  83. package/dist/helpers/splitIntervalByServiceHours.js +0 -30
  84. package/dist/helpers/splitIntervalByServiceHours.js.map +0 -1
  85. package/dist/helpers/splitIntervalByServiceHours.test.d.ts +0 -1
  86. package/dist/helpers/splitIntervalByServiceHours.test.js +0 -152
  87. package/dist/helpers/splitIntervalByServiceHours.test.js.map +0 -1
  88. package/dist/helpers/sumIntervalDuration.d.ts +0 -2
  89. package/dist/helpers/sumIntervalDuration.js +0 -9
  90. package/dist/helpers/sumIntervalDuration.js.map +0 -1
  91. package/dist/llm/client.d.ts +0 -2
  92. package/dist/llm/client.js +0 -5
  93. package/dist/llm/client.js.map +0 -1
  94. package/dist/llm/common/MemoryStore.d.ts +0 -21
  95. package/dist/llm/common/MemoryStore.js +0 -100
  96. package/dist/llm/common/MemoryStore.js.map +0 -1
  97. package/dist/llm/common/MemoryStore.test.d.ts +0 -1
  98. package/dist/llm/common/MemoryStore.test.js +0 -225
  99. package/dist/llm/common/MemoryStore.test.js.map +0 -1
  100. package/dist/llm/common/formatCurrentState.d.ts +0 -10
  101. package/dist/llm/common/formatCurrentState.js +0 -342
  102. package/dist/llm/common/formatCurrentState.js.map +0 -1
  103. package/dist/llm/common/tool.d.ts +0 -32
  104. package/dist/llm/common/tool.js +0 -6
  105. package/dist/llm/common/tool.js.map +0 -1
  106. package/dist/llm/functions/extractClaimsFromNewEvidence/eval.test.d.ts +0 -1
  107. package/dist/llm/functions/extractClaimsFromNewEvidence/eval.test.js +0 -433
  108. package/dist/llm/functions/extractClaimsFromNewEvidence/eval.test.js.map +0 -1
  109. package/dist/llm/functions/extractClaimsFromNewEvidence/index.d.ts +0 -18
  110. package/dist/llm/functions/extractClaimsFromNewEvidence/index.js +0 -153
  111. package/dist/llm/functions/extractClaimsFromNewEvidence/index.js.map +0 -1
  112. package/dist/llm/functions/extractClaimsFromNewEvidence/prompt.d.ts +0 -1
  113. package/dist/llm/functions/extractClaimsFromNewEvidence/prompt.js +0 -168
  114. package/dist/llm/functions/extractClaimsFromNewEvidence/prompt.js.map +0 -1
  115. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindLinesTool.d.ts +0 -19
  116. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindLinesTool.js +0 -65
  117. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindLinesTool.js.map +0 -1
  118. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindServicesTool.d.ts +0 -21
  119. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindServicesTool.js +0 -115
  120. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindServicesTool.js.map +0 -1
  121. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindStationsTool.d.ts +0 -24
  122. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindStationsTool.js +0 -110
  123. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindStationsTool.js.map +0 -1
  124. package/dist/llm/functions/generateIssueTitleAndSlug/index.d.ts +0 -14
  125. package/dist/llm/functions/generateIssueTitleAndSlug/index.js +0 -38
  126. package/dist/llm/functions/generateIssueTitleAndSlug/index.js.map +0 -1
  127. package/dist/llm/functions/generateIssueTitleAndSlug/prompt.d.ts +0 -1
  128. package/dist/llm/functions/generateIssueTitleAndSlug/prompt.js +0 -23
  129. package/dist/llm/functions/generateIssueTitleAndSlug/prompt.js.map +0 -1
  130. package/dist/llm/functions/translate/index.d.ts +0 -1
  131. package/dist/llm/functions/translate/index.js +0 -59
  132. package/dist/llm/functions/translate/index.js.map +0 -1
  133. package/dist/llm/functions/triageNewEvidence/eval.test.d.ts +0 -1
  134. package/dist/llm/functions/triageNewEvidence/eval.test.js +0 -139
  135. package/dist/llm/functions/triageNewEvidence/eval.test.js.map +0 -1
  136. package/dist/llm/functions/triageNewEvidence/index.d.ts +0 -37
  137. package/dist/llm/functions/triageNewEvidence/index.js +0 -121
  138. package/dist/llm/functions/triageNewEvidence/index.js.map +0 -1
  139. package/dist/llm/functions/triageNewEvidence/prompt.d.ts +0 -1
  140. package/dist/llm/functions/triageNewEvidence/prompt.js +0 -60
  141. package/dist/llm/functions/triageNewEvidence/prompt.js.map +0 -1
  142. package/dist/llm/functions/triageNewEvidence/tools/FindIssuesTool.d.ts +0 -19
  143. package/dist/llm/functions/triageNewEvidence/tools/FindIssuesTool.js +0 -65
  144. package/dist/llm/functions/triageNewEvidence/tools/FindIssuesTool.js.map +0 -1
  145. package/dist/llm/functions/triageNewEvidence/tools/GetIssueTool.d.ts +0 -19
  146. package/dist/llm/functions/triageNewEvidence/tools/GetIssueTool.js +0 -37
  147. package/dist/llm/functions/triageNewEvidence/tools/GetIssueTool.js.map +0 -1
  148. package/dist/repo/MRTDownRepository.d.ts +0 -23
  149. package/dist/repo/MRTDownRepository.js +0 -28
  150. package/dist/repo/MRTDownRepository.js.map +0 -1
  151. package/dist/repo/common/FileStore.d.ts +0 -12
  152. package/dist/repo/common/FileStore.js +0 -27
  153. package/dist/repo/common/FileStore.js.map +0 -1
  154. package/dist/repo/common/StandardRepository.d.ts +0 -32
  155. package/dist/repo/common/StandardRepository.js +0 -58
  156. package/dist/repo/common/StandardRepository.js.map +0 -1
  157. package/dist/repo/common/store.d.ts +0 -29
  158. package/dist/repo/common/store.js +0 -2
  159. package/dist/repo/common/store.js.map +0 -1
  160. package/dist/repo/issue/IssueRepository.d.ts +0 -36
  161. package/dist/repo/issue/IssueRepository.js +0 -177
  162. package/dist/repo/issue/IssueRepository.js.map +0 -1
  163. package/dist/repo/issue/helpers/deriveCurrentState.d.ts +0 -51
  164. package/dist/repo/issue/helpers/deriveCurrentState.js +0 -113
  165. package/dist/repo/issue/helpers/deriveCurrentState.js.map +0 -1
  166. package/dist/repo/issue/helpers/deriveCurrentState.test.d.ts +0 -1
  167. package/dist/repo/issue/helpers/deriveCurrentState.test.js +0 -477
  168. package/dist/repo/issue/helpers/deriveCurrentState.test.js.map +0 -1
  169. package/dist/repo/landmark/LandmarkRepository.d.ts +0 -7
  170. package/dist/repo/landmark/LandmarkRepository.js +0 -12
  171. package/dist/repo/landmark/LandmarkRepository.js.map +0 -1
  172. package/dist/repo/line/LineRepository.d.ts +0 -13
  173. package/dist/repo/line/LineRepository.js +0 -32
  174. package/dist/repo/line/LineRepository.js.map +0 -1
  175. package/dist/repo/operator/OperatorRepository.d.ts +0 -7
  176. package/dist/repo/operator/OperatorRepository.js +0 -12
  177. package/dist/repo/operator/OperatorRepository.js.map +0 -1
  178. package/dist/repo/service/ServiceRepository.d.ts +0 -19
  179. package/dist/repo/service/ServiceRepository.js +0 -39
  180. package/dist/repo/service/ServiceRepository.js.map +0 -1
  181. package/dist/repo/station/StationRepository.d.ts +0 -13
  182. package/dist/repo/station/StationRepository.js +0 -30
  183. package/dist/repo/station/StationRepository.js.map +0 -1
  184. package/dist/repo/town/TownRepository.d.ts +0 -7
  185. package/dist/repo/town/TownRepository.js +0 -12
  186. package/dist/repo/town/TownRepository.js.map +0 -1
  187. package/dist/scripts/ingestViaWebhook.d.ts +0 -1
  188. package/dist/scripts/ingestViaWebhook.js +0 -9
  189. package/dist/scripts/ingestViaWebhook.js.map +0 -1
  190. package/dist/util/assert.d.ts +0 -1
  191. package/dist/util/assert.js +0 -6
  192. package/dist/util/assert.js.map +0 -1
  193. package/dist/util/ingestContent/helpers/getSlugDateTimeFromClaims.d.ts +0 -7
  194. package/dist/util/ingestContent/helpers/getSlugDateTimeFromClaims.js +0 -24
  195. package/dist/util/ingestContent/helpers/getSlugDateTimeFromClaims.js.map +0 -1
  196. package/dist/util/ingestContent/index.d.ts +0 -12
  197. package/dist/util/ingestContent/index.js +0 -171
  198. package/dist/util/ingestContent/index.js.map +0 -1
  199. package/dist/util/ingestContent/types.d.ts +0 -32
  200. package/dist/util/ingestContent/types.js +0 -2
  201. package/dist/util/ingestContent/types.js.map +0 -1
  202. package/dist/validators/buildContext.d.ts +0 -7
  203. package/dist/validators/buildContext.js +0 -164
  204. package/dist/validators/buildContext.js.map +0 -1
  205. package/dist/validators/index.d.ts +0 -17
  206. package/dist/validators/index.js +0 -58
  207. package/dist/validators/index.js.map +0 -1
  208. package/dist/validators/issue.d.ts +0 -13
  209. package/dist/validators/issue.js +0 -220
  210. package/dist/validators/issue.js.map +0 -1
  211. package/dist/validators/landmark.d.ts +0 -7
  212. package/dist/validators/landmark.js +0 -43
  213. package/dist/validators/landmark.js.map +0 -1
  214. package/dist/validators/line.d.ts +0 -8
  215. package/dist/validators/line.js +0 -87
  216. package/dist/validators/line.js.map +0 -1
  217. package/dist/validators/operator.d.ts +0 -7
  218. package/dist/validators/operator.js +0 -43
  219. package/dist/validators/operator.js.map +0 -1
  220. package/dist/validators/service.d.ts +0 -8
  221. package/dist/validators/service.js +0 -87
  222. package/dist/validators/service.js.map +0 -1
  223. package/dist/validators/station.d.ts +0 -8
  224. package/dist/validators/station.js +0 -93
  225. package/dist/validators/station.js.map +0 -1
  226. package/dist/validators/town.d.ts +0 -7
  227. package/dist/validators/town.js +0 -43
  228. package/dist/validators/town.js.map +0 -1
  229. package/dist/validators/types.d.ts +0 -19
  230. package/dist/validators/types.js +0 -2
  231. package/dist/validators/types.js.map +0 -1
  232. package/dist/validators/utils.d.ts +0 -2
  233. package/dist/validators/utils.js +0 -9
  234. package/dist/validators/utils.js.map +0 -1
  235. package/dist/write/MRTDownWriter.d.ts +0 -27
  236. package/dist/write/MRTDownWriter.js +0 -27
  237. package/dist/write/MRTDownWriter.js.map +0 -1
  238. package/dist/write/common/FileWriteStore.d.ts +0 -13
  239. package/dist/write/common/FileWriteStore.js +0 -31
  240. package/dist/write/common/FileWriteStore.js.map +0 -1
  241. package/dist/write/common/StandardWriter.d.ts +0 -14
  242. package/dist/write/common/StandardWriter.js +0 -17
  243. package/dist/write/common/StandardWriter.js.map +0 -1
  244. package/dist/write/common/store.d.ts +0 -32
  245. package/dist/write/common/store.js +0 -2
  246. package/dist/write/common/store.js.map +0 -1
  247. package/dist/write/id/IdGenerator.d.ts +0 -18
  248. package/dist/write/id/IdGenerator.js +0 -23
  249. package/dist/write/id/IdGenerator.js.map +0 -1
  250. package/dist/write/issue/IssueWriter.d.ts +0 -12
  251. package/dist/write/issue/IssueWriter.js +0 -33
  252. package/dist/write/issue/IssueWriter.js.map +0 -1
@@ -1,477 +0,0 @@
1
- import { describe, expect, test } from 'vitest';
2
- import { keyForAffectedEntity } from '../../../helpers/keyForAffectedEntity.js';
3
- import { deriveCurrentState } from './deriveCurrentState.js';
4
- const defaultTarget = { type: 'service', serviceId: 'NSL' };
5
- const nslKey = keyForAffectedEntity(defaultTarget);
6
- describe('deriveCurrentState', () => {
7
- const createMockIssue = () => ({
8
- id: '2025-01-01-test-issue',
9
- type: 'disruption',
10
- title: {
11
- 'en-SG': 'Test Issue',
12
- 'zh-Hans': null,
13
- ms: null,
14
- ta: null,
15
- },
16
- titleMeta: {
17
- source: 'test',
18
- },
19
- });
20
- const createMockBundle = (impact) => ({
21
- issue: createMockIssue(),
22
- evidence: [],
23
- impactEvents: impact,
24
- path: 'test/path',
25
- });
26
- test('returns empty state for bundle with no impacts', () => {
27
- const bundle = createMockBundle([]);
28
- const result = deriveCurrentState(bundle);
29
- expect(result).toEqual({
30
- services: {},
31
- servicesProvenance: {},
32
- facilities: {},
33
- facilitiesProvenance: {},
34
- impactEventIds: [],
35
- });
36
- });
37
- test('handles service_effects.set impact', () => {
38
- const effect = { kind: 'delay', duration: null };
39
- const bundle = createMockBundle([
40
- {
41
- id: 'ie_test_001',
42
- type: 'service_effects.set',
43
- entity: defaultTarget,
44
- ts: '2025-01-01T10:00:00Z',
45
- effect,
46
- basis: {
47
- evidenceId: 'evidence-1',
48
- },
49
- },
50
- ]);
51
- const result = deriveCurrentState(bundle);
52
- expect(result.services[nslKey]).toMatchObject({
53
- id: 'NSL',
54
- effect,
55
- scopes: [],
56
- periods: [],
57
- });
58
- expect(result.servicesProvenance[nslKey]).toEqual({
59
- effect: { evidenceId: 'evidence-1' },
60
- });
61
- expect(result.impactEventIds).toEqual(['ie_test_001']);
62
- });
63
- test('handles periods_set impact', () => {
64
- const periods = [
65
- {
66
- kind: 'fixed',
67
- startAt: '2025-01-01T10:00:00+08:00',
68
- endAt: '2025-01-01T12:00:00+08:00',
69
- },
70
- {
71
- kind: 'fixed',
72
- startAt: '2025-01-01T14:00:00+08:00',
73
- endAt: null,
74
- },
75
- ];
76
- const bundle = createMockBundle([
77
- {
78
- id: 'ie_test_001',
79
- type: 'periods.set',
80
- entity: defaultTarget,
81
- ts: '2025-01-01T10:00:00Z',
82
- periods,
83
- basis: {
84
- evidenceId: 'evidence-3',
85
- },
86
- },
87
- ]);
88
- const result = deriveCurrentState(bundle);
89
- expect(result.services[nslKey]).toMatchObject({
90
- id: 'NSL',
91
- effect: null,
92
- scopes: [],
93
- periods,
94
- });
95
- expect(result.servicesProvenance[nslKey]).toEqual({
96
- periods: { evidenceId: 'evidence-3' },
97
- });
98
- expect(result.impactEventIds).toEqual(['ie_test_001']);
99
- });
100
- test('handles causes.set impact', () => {
101
- const causes = ['signal.fault', 'track.fault'];
102
- const bundle = createMockBundle([
103
- {
104
- id: 'ie_test_cause_001',
105
- type: 'causes.set',
106
- entity: defaultTarget,
107
- ts: '2025-01-01T10:00:00Z',
108
- causes: [...causes],
109
- basis: { evidenceId: 'evidence-cause' },
110
- },
111
- ]);
112
- const result = deriveCurrentState(bundle);
113
- expect(result.services[nslKey]).toMatchObject({
114
- id: 'NSL',
115
- effect: null,
116
- scopes: [],
117
- periods: [],
118
- causes,
119
- });
120
- expect(result.servicesProvenance[nslKey]).toEqual({
121
- causes: { evidenceId: 'evidence-cause' },
122
- });
123
- expect(result.impactEventIds).toEqual(['ie_test_cause_001']);
124
- });
125
- test('handles service_scopes_set impact', () => {
126
- const serviceScopes = [
127
- {
128
- type: 'service.whole',
129
- },
130
- {
131
- type: 'service.segment',
132
- fromStationId: 'station-1',
133
- toStationId: 'station-2',
134
- },
135
- ];
136
- const bundle = createMockBundle([
137
- {
138
- id: 'ie_test_001',
139
- type: 'service_scopes.set',
140
- entity: defaultTarget,
141
- ts: '2025-01-01T10:00:00Z',
142
- serviceScopes,
143
- basis: {
144
- evidenceId: 'evidence-5',
145
- },
146
- },
147
- ]);
148
- const result = deriveCurrentState(bundle);
149
- expect(result.services[nslKey]).toMatchObject({
150
- id: 'NSL',
151
- effect: null,
152
- scopes: serviceScopes,
153
- periods: [],
154
- });
155
- expect(result.servicesProvenance[nslKey]).toEqual({
156
- scopes: { evidenceId: 'evidence-5' },
157
- });
158
- expect(result.impactEventIds).toEqual(['ie_test_001']);
159
- });
160
- test('handles multiple impacts - later impacts overwrite earlier ones', () => {
161
- const firstEffect = { kind: 'delay', duration: null };
162
- const secondEffect = { kind: 'no-service' };
163
- const bundle = createMockBundle([
164
- {
165
- id: 'ie_test_001',
166
- type: 'service_effects.set',
167
- entity: defaultTarget,
168
- ts: '2025-01-01T10:00:00Z',
169
- effect: firstEffect,
170
- basis: {
171
- evidenceId: 'evidence-1',
172
- },
173
- },
174
- {
175
- id: 'ie_test_002',
176
- type: 'service_effects.set',
177
- entity: defaultTarget,
178
- ts: '2025-01-01T11:00:00Z',
179
- effect: secondEffect,
180
- basis: {
181
- evidenceId: 'evidence-2',
182
- },
183
- },
184
- ]);
185
- const result = deriveCurrentState(bundle);
186
- expect(result.services[nslKey].effect).toEqual(secondEffect);
187
- expect(result.servicesProvenance[nslKey].effect?.evidenceId).toBe('evidence-2');
188
- expect(result.impactEventIds).toEqual(['ie_test_002']);
189
- });
190
- test('handles mixed impact types', () => {
191
- const effect = { kind: 'delay', duration: null };
192
- const periods = [
193
- {
194
- kind: 'fixed',
195
- startAt: '2025-01-01T10:00:00+08:00',
196
- endAt: '2025-01-01T12:00:00+08:00',
197
- },
198
- ];
199
- const serviceScopes = [
200
- {
201
- type: 'service.point',
202
- stationId: 'station-1',
203
- },
204
- ];
205
- const bundle = createMockBundle([
206
- {
207
- id: 'ie_test_001',
208
- type: 'service_effects.set',
209
- entity: defaultTarget,
210
- ts: '2025-01-01T10:00:00Z',
211
- effect,
212
- basis: {
213
- evidenceId: 'evidence-1',
214
- },
215
- },
216
- {
217
- id: 'ie_test_002',
218
- type: 'periods.set',
219
- entity: defaultTarget,
220
- ts: '2025-01-01T11:00:00Z',
221
- periods,
222
- basis: {
223
- evidenceId: 'evidence-2',
224
- },
225
- },
226
- {
227
- id: 'ie_test_003',
228
- type: 'service_scopes.set',
229
- entity: defaultTarget,
230
- ts: '2025-01-01T12:00:00Z',
231
- serviceScopes,
232
- basis: {
233
- evidenceId: 'evidence-3',
234
- },
235
- },
236
- ]);
237
- const result = deriveCurrentState(bundle);
238
- expect(result.services[nslKey].effect).toEqual(effect);
239
- expect(result.services[nslKey].periods).toEqual(periods);
240
- expect(result.services[nslKey].scopes).toEqual(serviceScopes);
241
- expect(result.servicesProvenance[nslKey].effect?.evidenceId).toBe('evidence-1');
242
- expect(result.servicesProvenance[nslKey].periods?.evidenceId).toBe('evidence-2');
243
- expect(result.servicesProvenance[nslKey].scopes?.evidenceId).toBe('evidence-3');
244
- expect(result.impactEventIds).toEqual([
245
- 'ie_test_001',
246
- 'ie_test_003',
247
- 'ie_test_002',
248
- ]);
249
- });
250
- test('handles all service effect kinds', () => {
251
- const effectKinds = [
252
- 'delay',
253
- 'no-service',
254
- 'reduced-service',
255
- 'service-hours-adjustment',
256
- ];
257
- for (const kind of effectKinds) {
258
- const effect = kind === 'delay' ? { kind: 'delay', duration: null } : { kind };
259
- const bundle = createMockBundle([
260
- {
261
- id: 'ie_test_001',
262
- type: 'service_effects.set',
263
- entity: defaultTarget,
264
- ts: '2025-01-01T10:00:00Z',
265
- effect,
266
- basis: {
267
- evidenceId: 'evidence-1',
268
- },
269
- },
270
- ]);
271
- const result = deriveCurrentState(bundle);
272
- expect(result.services[nslKey].effect).toEqual(effect);
273
- }
274
- });
275
- test('handles all scope types', () => {
276
- const allScopes = [
277
- {
278
- type: 'service.whole',
279
- },
280
- {
281
- type: 'service.segment',
282
- fromStationId: 'station-1',
283
- toStationId: 'station-2',
284
- },
285
- {
286
- type: 'service.point',
287
- stationId: 'station-3',
288
- },
289
- ];
290
- const bundle = createMockBundle([
291
- {
292
- id: 'ie_test_001',
293
- type: 'service_scopes.set',
294
- entity: defaultTarget,
295
- ts: '2025-01-01T10:00:00Z',
296
- serviceScopes: allScopes,
297
- basis: {
298
- evidenceId: 'evidence-1',
299
- },
300
- },
301
- ]);
302
- const result = deriveCurrentState(bundle);
303
- expect(result.services[nslKey].scopes).toEqual(allScopes);
304
- expect(result.services[nslKey].scopes).toHaveLength(3);
305
- expect(result.impactEventIds).toEqual(['ie_test_001']);
306
- });
307
- test('handles empty arrays in impacts', () => {
308
- const bundle = createMockBundle([
309
- {
310
- id: 'ie_test_001',
311
- type: 'service_effects.set',
312
- entity: defaultTarget,
313
- ts: '2025-01-01T10:00:00Z',
314
- effect: { kind: 'no-service' },
315
- basis: {
316
- evidenceId: 'evidence-1',
317
- },
318
- },
319
- {
320
- id: 'ie_test_002',
321
- type: 'periods.set',
322
- entity: defaultTarget,
323
- ts: '2025-01-01T11:00:00Z',
324
- periods: [],
325
- basis: {
326
- evidenceId: 'evidence-2',
327
- },
328
- },
329
- {
330
- id: 'ie_test_003',
331
- type: 'service_scopes.set',
332
- entity: defaultTarget,
333
- ts: '2025-01-01T12:00:00Z',
334
- serviceScopes: [],
335
- basis: {
336
- evidenceId: 'evidence-3',
337
- },
338
- },
339
- ]);
340
- const result = deriveCurrentState(bundle);
341
- expect(result.services[nslKey].effect).toEqual({ kind: 'no-service' });
342
- expect(result.services[nslKey].periods).toEqual([]);
343
- expect(result.services[nslKey].scopes).toEqual([]);
344
- expect(result.impactEventIds).toEqual([
345
- 'ie_test_001',
346
- 'ie_test_003',
347
- 'ie_test_002',
348
- ]);
349
- });
350
- test('preserves order of impacts when processing', () => {
351
- const firstPeriods = [
352
- {
353
- kind: 'fixed',
354
- startAt: '2025-01-01T10:00:00+08:00',
355
- endAt: '2025-01-01T12:00:00+08:00',
356
- },
357
- ];
358
- const secondPeriods = [
359
- {
360
- kind: 'fixed',
361
- startAt: '2025-01-01T14:00:00+08:00',
362
- endAt: null,
363
- },
364
- ];
365
- const bundle = createMockBundle([
366
- {
367
- id: 'ie_test_001',
368
- type: 'periods.set',
369
- entity: defaultTarget,
370
- ts: '2025-01-01T10:00:00Z',
371
- periods: firstPeriods,
372
- basis: {
373
- evidenceId: 'evidence-1',
374
- },
375
- },
376
- {
377
- id: 'ie_test_002',
378
- type: 'periods.set',
379
- entity: defaultTarget,
380
- ts: '2025-01-01T11:00:00Z',
381
- periods: secondPeriods,
382
- basis: {
383
- evidenceId: 'evidence-2',
384
- },
385
- },
386
- ]);
387
- const result = deriveCurrentState(bundle);
388
- expect(result.services[nslKey].periods).toEqual(secondPeriods);
389
- expect(result.servicesProvenance[nslKey].periods?.evidenceId).toBe('evidence-2');
390
- expect(result.impactEventIds).toEqual(['ie_test_002']);
391
- });
392
- test('groups impacts by target - different targets produce separate entries', () => {
393
- const nslTarget = { type: 'service', serviceId: 'NSL' };
394
- const ewlTarget = { type: 'service', serviceId: 'EWL' };
395
- const nslKeyLocal = keyForAffectedEntity(nslTarget);
396
- const ewlKey = keyForAffectedEntity(ewlTarget);
397
- const bundle = createMockBundle([
398
- {
399
- id: 'ie_test_001',
400
- type: 'service_effects.set',
401
- entity: nslTarget,
402
- ts: '2025-01-01T10:00:00Z',
403
- effect: { kind: 'delay', duration: null },
404
- basis: { evidenceId: 'evidence-1' },
405
- },
406
- {
407
- id: 'ie_test_002',
408
- type: 'service_effects.set',
409
- entity: ewlTarget,
410
- ts: '2025-01-01T10:00:00Z',
411
- effect: { kind: 'no-service' },
412
- basis: { evidenceId: 'evidence-2' },
413
- },
414
- ]);
415
- const result = deriveCurrentState(bundle);
416
- expect(Object.keys(result.services)).toHaveLength(2);
417
- expect(result.services[nslKeyLocal].effect).toEqual({
418
- kind: 'delay',
419
- duration: null,
420
- });
421
- expect(result.services[nslKeyLocal]).toMatchObject({ id: 'NSL' });
422
- expect(result.services[ewlKey].effect).toEqual({ kind: 'no-service' });
423
- expect(result.services[ewlKey]).toMatchObject({ id: 'EWL' });
424
- expect(result.impactEventIds).toEqual(['ie_test_002']);
425
- });
426
- test('handles facility impacts', () => {
427
- const facilityEntity = {
428
- type: 'facility',
429
- stationId: 'JUR',
430
- kind: 'lift',
431
- };
432
- const facilityKey = keyForAffectedEntity(facilityEntity);
433
- const bundle = createMockBundle([
434
- {
435
- id: 'ie_test_001',
436
- type: 'facility_effects.set',
437
- entity: facilityEntity,
438
- ts: '2025-01-01T10:00:00Z',
439
- effect: { kind: 'facility-out-of-service' },
440
- basis: { evidenceId: 'evidence-1' },
441
- },
442
- {
443
- id: 'ie_test_002',
444
- type: 'periods.set',
445
- entity: facilityEntity,
446
- ts: '2025-01-01T10:00:00Z',
447
- periods: [
448
- {
449
- kind: 'fixed',
450
- startAt: '2025-01-01T10:00:00+08:00',
451
- endAt: '2025-01-01T12:00:00+08:00',
452
- },
453
- ],
454
- basis: { evidenceId: 'evidence-2' },
455
- },
456
- ]);
457
- const result = deriveCurrentState(bundle);
458
- expect(result.facilities[facilityKey]).toMatchObject({
459
- stationId: 'JUR',
460
- kind: 'lift',
461
- effect: { kind: 'facility-out-of-service' },
462
- periods: [
463
- {
464
- kind: 'fixed',
465
- startAt: '2025-01-01T10:00:00+08:00',
466
- endAt: '2025-01-01T12:00:00+08:00',
467
- },
468
- ],
469
- });
470
- expect(result.facilitiesProvenance[facilityKey]).toEqual({
471
- effect: { evidenceId: 'evidence-1' },
472
- periods: { evidenceId: 'evidence-2' },
473
- });
474
- expect(result.impactEventIds).toEqual(['ie_test_002', 'ie_test_001']);
475
- });
476
- });
477
- //# sourceMappingURL=deriveCurrentState.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"deriveCurrentState.test.js","sourceRoot":"/","sources":["repo/issue/helpers/deriveCurrentState.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { describe, expect, test } from 'vitest';\nimport type { IssueBundle } from '../../../schema/issue/bundle.js';\nimport type { Period } from '../../../schema/issue/period.js';\nimport type { ServiceEffect } from '../../../schema/issue/serviceEffect.js';\nimport type { ServiceScope } from '../../../schema/issue/serviceScope.js';\nimport { keyForAffectedEntity } from '../../../helpers/keyForAffectedEntity.js';\nimport { deriveCurrentState } from './deriveCurrentState.js';\n\nconst defaultTarget = { type: 'service' as const, serviceId: 'NSL' };\nconst nslKey = keyForAffectedEntity(defaultTarget);\n\ndescribe('deriveCurrentState', () => {\n const createMockIssue = () => ({\n id: '2025-01-01-test-issue',\n type: 'disruption' as const,\n title: {\n 'en-SG': 'Test Issue',\n 'zh-Hans': null,\n ms: null,\n ta: null,\n },\n titleMeta: {\n source: 'test',\n },\n });\n\n const createMockBundle = (\n impact: IssueBundle['impactEvents'],\n ): IssueBundle => ({\n issue: createMockIssue(),\n evidence: [],\n impactEvents: impact,\n path: 'test/path',\n });\n\n test('returns empty state for bundle with no impacts', () => {\n const bundle = createMockBundle([]);\n const result = deriveCurrentState(bundle);\n\n expect(result).toEqual({\n services: {},\n servicesProvenance: {},\n facilities: {},\n facilitiesProvenance: {},\n impactEventIds: [],\n });\n });\n\n test('handles service_effects.set impact', () => {\n const effect: ServiceEffect = { kind: 'delay', duration: null };\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n effect,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey]).toMatchObject({\n id: 'NSL',\n effect,\n scopes: [],\n periods: [],\n });\n expect(result.servicesProvenance[nslKey]).toEqual({\n effect: { evidenceId: 'evidence-1' },\n });\n expect(result.impactEventIds).toEqual(['ie_test_001']);\n });\n\n test('handles periods_set impact', () => {\n const periods: Period[] = [\n {\n kind: 'fixed',\n startAt: '2025-01-01T10:00:00+08:00',\n endAt: '2025-01-01T12:00:00+08:00',\n },\n {\n kind: 'fixed',\n startAt: '2025-01-01T14:00:00+08:00',\n endAt: null,\n },\n ];\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'periods.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n periods,\n basis: {\n evidenceId: 'evidence-3',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey]).toMatchObject({\n id: 'NSL',\n effect: null,\n scopes: [],\n periods,\n });\n expect(result.servicesProvenance[nslKey]).toEqual({\n periods: { evidenceId: 'evidence-3' },\n });\n expect(result.impactEventIds).toEqual(['ie_test_001']);\n });\n\n test('handles causes.set impact', () => {\n const causes = ['signal.fault', 'track.fault'] as const;\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_cause_001',\n type: 'causes.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n causes: [...causes],\n basis: { evidenceId: 'evidence-cause' },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey]).toMatchObject({\n id: 'NSL',\n effect: null,\n scopes: [],\n periods: [],\n causes,\n });\n expect(result.servicesProvenance[nslKey]).toEqual({\n causes: { evidenceId: 'evidence-cause' },\n });\n expect(result.impactEventIds).toEqual(['ie_test_cause_001']);\n });\n\n test('handles service_scopes_set impact', () => {\n const serviceScopes: ServiceScope[] = [\n {\n type: 'service.whole',\n },\n {\n type: 'service.segment',\n fromStationId: 'station-1',\n toStationId: 'station-2',\n },\n ];\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_scopes.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n serviceScopes,\n basis: {\n evidenceId: 'evidence-5',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey]).toMatchObject({\n id: 'NSL',\n effect: null,\n scopes: serviceScopes,\n periods: [],\n });\n expect(result.servicesProvenance[nslKey]).toEqual({\n scopes: { evidenceId: 'evidence-5' },\n });\n expect(result.impactEventIds).toEqual(['ie_test_001']);\n });\n\n test('handles multiple impacts - later impacts overwrite earlier ones', () => {\n const firstEffect: ServiceEffect = { kind: 'delay', duration: null };\n const secondEffect: ServiceEffect = { kind: 'no-service' };\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n effect: firstEffect,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n {\n id: 'ie_test_002',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T11:00:00Z',\n effect: secondEffect,\n basis: {\n evidenceId: 'evidence-2',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].effect).toEqual(secondEffect);\n expect(result.servicesProvenance[nslKey].effect?.evidenceId).toBe(\n 'evidence-2',\n );\n expect(result.impactEventIds).toEqual(['ie_test_002']);\n });\n\n test('handles mixed impact types', () => {\n const effect: ServiceEffect = { kind: 'delay', duration: null };\n const periods: Period[] = [\n {\n kind: 'fixed',\n startAt: '2025-01-01T10:00:00+08:00',\n endAt: '2025-01-01T12:00:00+08:00',\n },\n ];\n const serviceScopes: ServiceScope[] = [\n {\n type: 'service.point',\n stationId: 'station-1',\n },\n ];\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n effect,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n {\n id: 'ie_test_002',\n type: 'periods.set',\n entity: defaultTarget,\n ts: '2025-01-01T11:00:00Z',\n periods,\n basis: {\n evidenceId: 'evidence-2',\n },\n },\n {\n id: 'ie_test_003',\n type: 'service_scopes.set',\n entity: defaultTarget,\n ts: '2025-01-01T12:00:00Z',\n serviceScopes,\n basis: {\n evidenceId: 'evidence-3',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].effect).toEqual(effect);\n expect(result.services[nslKey].periods).toEqual(periods);\n expect(result.services[nslKey].scopes).toEqual(serviceScopes);\n expect(result.servicesProvenance[nslKey].effect?.evidenceId).toBe(\n 'evidence-1',\n );\n expect(result.servicesProvenance[nslKey].periods?.evidenceId).toBe(\n 'evidence-2',\n );\n expect(result.servicesProvenance[nslKey].scopes?.evidenceId).toBe(\n 'evidence-3',\n );\n expect(result.impactEventIds).toEqual([\n 'ie_test_001',\n 'ie_test_003',\n 'ie_test_002',\n ]);\n });\n\n test('handles all service effect kinds', () => {\n const effectKinds: ServiceEffect['kind'][] = [\n 'delay',\n 'no-service',\n 'reduced-service',\n 'service-hours-adjustment',\n ];\n\n for (const kind of effectKinds) {\n const effect: ServiceEffect =\n kind === 'delay' ? { kind: 'delay', duration: null } : { kind };\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n effect,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].effect).toEqual(effect);\n }\n });\n\n test('handles all scope types', () => {\n const allScopes: ServiceScope[] = [\n {\n type: 'service.whole',\n },\n {\n type: 'service.segment',\n fromStationId: 'station-1',\n toStationId: 'station-2',\n },\n {\n type: 'service.point',\n stationId: 'station-3',\n },\n ];\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_scopes.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n serviceScopes: allScopes,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].scopes).toEqual(allScopes);\n expect(result.services[nslKey].scopes).toHaveLength(3);\n expect(result.impactEventIds).toEqual(['ie_test_001']);\n });\n\n test('handles empty arrays in impacts', () => {\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n effect: { kind: 'no-service' },\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n {\n id: 'ie_test_002',\n type: 'periods.set',\n entity: defaultTarget,\n ts: '2025-01-01T11:00:00Z',\n periods: [],\n basis: {\n evidenceId: 'evidence-2',\n },\n },\n {\n id: 'ie_test_003',\n type: 'service_scopes.set',\n entity: defaultTarget,\n ts: '2025-01-01T12:00:00Z',\n serviceScopes: [],\n basis: {\n evidenceId: 'evidence-3',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].effect).toEqual({ kind: 'no-service' });\n expect(result.services[nslKey].periods).toEqual([]);\n expect(result.services[nslKey].scopes).toEqual([]);\n expect(result.impactEventIds).toEqual([\n 'ie_test_001',\n 'ie_test_003',\n 'ie_test_002',\n ]);\n });\n\n test('preserves order of impacts when processing', () => {\n const firstPeriods: Period[] = [\n {\n kind: 'fixed',\n startAt: '2025-01-01T10:00:00+08:00',\n endAt: '2025-01-01T12:00:00+08:00',\n },\n ];\n const secondPeriods: Period[] = [\n {\n kind: 'fixed',\n startAt: '2025-01-01T14:00:00+08:00',\n endAt: null,\n },\n ];\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'periods.set',\n entity: defaultTarget,\n ts: '2025-01-01T10:00:00Z',\n periods: firstPeriods,\n basis: {\n evidenceId: 'evidence-1',\n },\n },\n {\n id: 'ie_test_002',\n type: 'periods.set',\n entity: defaultTarget,\n ts: '2025-01-01T11:00:00Z',\n periods: secondPeriods,\n basis: {\n evidenceId: 'evidence-2',\n },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.services[nslKey].periods).toEqual(secondPeriods);\n expect(result.servicesProvenance[nslKey].periods?.evidenceId).toBe(\n 'evidence-2',\n );\n expect(result.impactEventIds).toEqual(['ie_test_002']);\n });\n\n test('groups impacts by target - different targets produce separate entries', () => {\n const nslTarget = { type: 'service' as const, serviceId: 'NSL' };\n const ewlTarget = { type: 'service' as const, serviceId: 'EWL' };\n const nslKeyLocal = keyForAffectedEntity(nslTarget);\n const ewlKey = keyForAffectedEntity(ewlTarget);\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'service_effects.set',\n entity: nslTarget,\n ts: '2025-01-01T10:00:00Z',\n effect: { kind: 'delay', duration: null },\n basis: { evidenceId: 'evidence-1' },\n },\n {\n id: 'ie_test_002',\n type: 'service_effects.set',\n entity: ewlTarget,\n ts: '2025-01-01T10:00:00Z',\n effect: { kind: 'no-service' },\n basis: { evidenceId: 'evidence-2' },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(Object.keys(result.services)).toHaveLength(2);\n expect(result.services[nslKeyLocal].effect).toEqual({\n kind: 'delay',\n duration: null,\n });\n expect(result.services[nslKeyLocal]).toMatchObject({ id: 'NSL' });\n expect(result.services[ewlKey].effect).toEqual({ kind: 'no-service' });\n expect(result.services[ewlKey]).toMatchObject({ id: 'EWL' });\n expect(result.impactEventIds).toEqual(['ie_test_002']);\n });\n\n test('handles facility impacts', () => {\n const facilityEntity = {\n type: 'facility' as const,\n stationId: 'JUR',\n kind: 'lift' as const,\n };\n const facilityKey = keyForAffectedEntity(facilityEntity);\n\n const bundle = createMockBundle([\n {\n id: 'ie_test_001',\n type: 'facility_effects.set',\n entity: facilityEntity,\n ts: '2025-01-01T10:00:00Z',\n effect: { kind: 'facility-out-of-service' },\n basis: { evidenceId: 'evidence-1' },\n },\n {\n id: 'ie_test_002',\n type: 'periods.set',\n entity: facilityEntity,\n ts: '2025-01-01T10:00:00Z',\n periods: [\n {\n kind: 'fixed',\n startAt: '2025-01-01T10:00:00+08:00',\n endAt: '2025-01-01T12:00:00+08:00',\n },\n ],\n basis: { evidenceId: 'evidence-2' },\n },\n ]);\n\n const result = deriveCurrentState(bundle);\n\n expect(result.facilities[facilityKey]).toMatchObject({\n stationId: 'JUR',\n kind: 'lift',\n effect: { kind: 'facility-out-of-service' },\n periods: [\n {\n kind: 'fixed',\n startAt: '2025-01-01T10:00:00+08:00',\n endAt: '2025-01-01T12:00:00+08:00',\n },\n ],\n });\n expect(result.facilitiesProvenance[facilityKey]).toEqual({\n effect: { evidenceId: 'evidence-1' },\n periods: { evidenceId: 'evidence-2' },\n });\n expect(result.impactEventIds).toEqual(['ie_test_002', 'ie_test_001']);\n });\n});\n"]}
@@ -1,7 +0,0 @@
1
- import { type Landmark } from '../../schema/Landmark.js';
2
- import { StandardRepository } from '../common/StandardRepository.js';
3
- import type { IStore } from '../common/store.js';
4
- export declare class LandmarkRepository extends StandardRepository<Landmark> {
5
- constructor(store: IStore);
6
- protected parseItem(json: unknown): Landmark;
7
- }
@@ -1,12 +0,0 @@
1
- import { DIR_LANDMARK } from '../../constants.js';
2
- import { LandmarkSchema } from '../../schema/Landmark.js';
3
- import { StandardRepository } from '../common/StandardRepository.js';
4
- export class LandmarkRepository extends StandardRepository {
5
- constructor(store) {
6
- super(store, DIR_LANDMARK);
7
- }
8
- parseItem(json) {
9
- return LandmarkSchema.parse(json);
10
- }
11
- }
12
- //# sourceMappingURL=LandmarkRepository.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"LandmarkRepository.js","sourceRoot":"/","sources":["repo/landmark/LandmarkRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAiB,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAGrE,MAAM,OAAO,kBAAmB,SAAQ,kBAA4B;IAClE,YAAY,KAAa;QACvB,KAAK,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IAC7B,CAAC;IAES,SAAS,CAAC,IAAa;QAC/B,OAAO,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;CACF","sourcesContent":["import { DIR_LANDMARK } from '../../constants.js';\nimport { type Landmark, LandmarkSchema } from '../../schema/Landmark.js';\nimport { StandardRepository } from '../common/StandardRepository.js';\nimport type { IStore } from '../common/store.js';\n\nexport class LandmarkRepository extends StandardRepository<Landmark> {\n constructor(store: IStore) {\n super(store, DIR_LANDMARK);\n }\n\n protected parseItem(json: unknown): Landmark {\n return LandmarkSchema.parse(json);\n }\n}\n"]}
@@ -1,13 +0,0 @@
1
- import { type Line } from '../../schema/Line.js';
2
- import { StandardRepository } from '../common/StandardRepository.js';
3
- import type { IStore } from '../common/store.js';
4
- export declare class LineRepository extends StandardRepository<Line> {
5
- constructor(store: IStore);
6
- protected parseItem(json: unknown): Line;
7
- /**
8
- * Search lines by name.
9
- * @param names
10
- * @returns
11
- */
12
- searchByName(names: string[]): Line[];
13
- }
@@ -1,32 +0,0 @@
1
- import Fuse from 'fuse.js';
2
- import { DIR_LINE } from '../../constants.js';
3
- import { LineSchema } from '../../schema/Line.js';
4
- import { StandardRepository } from '../common/StandardRepository.js';
5
- export class LineRepository extends StandardRepository {
6
- constructor(store) {
7
- super(store, DIR_LINE);
8
- }
9
- parseItem(json) {
10
- return LineSchema.parse(json);
11
- }
12
- /**
13
- * Search lines by name.
14
- * @param names
15
- * @returns
16
- */
17
- searchByName(names) {
18
- this.loadAll();
19
- const fuse = new Fuse(Array.from(this.byId.values()), {
20
- keys: ['id', 'name.en-SG'],
21
- includeScore: true,
22
- threshold: 0.3,
23
- });
24
- const results = fuse.search({
25
- $or: names.flatMap((name) => {
26
- return [{ id: name }, { 'name.en-SG': name }];
27
- }),
28
- });
29
- return results.map((r) => r.item);
30
- }
31
- }
32
- //# sourceMappingURL=LineRepository.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"LineRepository.js","sourceRoot":"/","sources":["repo/line/LineRepository.ts"],"names":[],"mappings":"AAAA,OAAO,IAAyB,MAAM,SAAS,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAa,UAAU,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAGrE,MAAM,OAAO,cAAe,SAAQ,kBAAwB;IAC1D,YAAY,KAAa;QACvB,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;IACzB,CAAC;IAES,SAAS,CAAC,IAAa;QAC/B,OAAO,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAChC,CAAC;IAED;;;;OAIG;IACH,YAAY,CAAC,KAAe;QAC1B,IAAI,CAAC,OAAO,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,EAAE;YACpD,IAAI,EAAE,CAAC,IAAI,EAAE,YAAY,CAAC;YAC1B,YAAY,EAAE,IAAI;YAClB,SAAS,EAAE,GAAG;SACf,CAAC,CAAC;QACH,MAAM,OAAO,GAAG,IAAI,CAAC,MAAM,CAAC;YAC1B,GAAG,EAAE,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;gBAC1B,OAAO,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,YAAY,EAAE,IAAI,EAAE,CAAiB,CAAC;YAChE,CAAC,CAAC;SACH,CAAC,CAAC;QACH,OAAO,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;CACF","sourcesContent":["import Fuse, { type Expression } from 'fuse.js';\nimport { DIR_LINE } from '../../constants.js';\nimport { type Line, LineSchema } from '../../schema/Line.js';\nimport { StandardRepository } from '../common/StandardRepository.js';\nimport type { IStore } from '../common/store.js';\n\nexport class LineRepository extends StandardRepository<Line> {\n constructor(store: IStore) {\n super(store, DIR_LINE);\n }\n\n protected parseItem(json: unknown): Line {\n return LineSchema.parse(json);\n }\n\n /**\n * Search lines by name.\n * @param names\n * @returns\n */\n searchByName(names: string[]): Line[] {\n this.loadAll();\n const fuse = new Fuse(Array.from(this.byId.values()), {\n keys: ['id', 'name.en-SG'],\n includeScore: true,\n threshold: 0.3,\n });\n const results = fuse.search({\n $or: names.flatMap((name) => {\n return [{ id: name }, { 'name.en-SG': name }] as Expression[];\n }),\n });\n return results.map((r) => r.item);\n }\n}\n"]}
@@ -1,7 +0,0 @@
1
- import { type Operator } from '../../schema/Operator.js';
2
- import { StandardRepository } from '../common/StandardRepository.js';
3
- import type { IStore } from '../common/store.js';
4
- export declare class OperatorRepository extends StandardRepository<Operator> {
5
- constructor(store: IStore);
6
- protected parseItem(json: unknown): Operator;
7
- }
@@ -1,12 +0,0 @@
1
- import { DIR_OPERATOR } from '../../constants.js';
2
- import { OperatorSchema } from '../../schema/Operator.js';
3
- import { StandardRepository } from '../common/StandardRepository.js';
4
- export class OperatorRepository extends StandardRepository {
5
- constructor(store) {
6
- super(store, DIR_OPERATOR);
7
- }
8
- parseItem(json) {
9
- return OperatorSchema.parse(json);
10
- }
11
- }
12
- //# sourceMappingURL=OperatorRepository.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"OperatorRepository.js","sourceRoot":"/","sources":["repo/operator/OperatorRepository.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAiB,cAAc,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAGrE,MAAM,OAAO,kBAAmB,SAAQ,kBAA4B;IAClE,YAAY,KAAa;QACvB,KAAK,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IAC7B,CAAC;IAES,SAAS,CAAC,IAAa;QAC/B,OAAO,cAAc,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;CACF","sourcesContent":["import { DIR_OPERATOR } from '../../constants.js';\nimport { type Operator, OperatorSchema } from '../../schema/Operator.js';\nimport { StandardRepository } from '../common/StandardRepository.js';\nimport type { IStore } from '../common/store.js';\n\nexport class OperatorRepository extends StandardRepository<Operator> {\n constructor(store: IStore) {\n super(store, DIR_OPERATOR);\n }\n\n protected parseItem(json: unknown): Operator {\n return OperatorSchema.parse(json);\n }\n}\n"]}