@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,189 +0,0 @@
1
- import { readFile } from 'node:fs/promises';
2
- import { join } from 'node:path';
3
- import { createInterface } from 'node:readline';
4
- import { IssueTypeSchema } from '../../schema/issue/issueType.js';
5
- import { FileWriteStore } from '../../write/common/FileWriteStore.js';
6
- import { MRTDownWriter } from '../../write/MRTDownWriter.js';
7
- function translationsFromEn(en) {
8
- return {
9
- 'en-SG': en,
10
- 'zh-Hans': null,
11
- ms: null,
12
- ta: null,
13
- };
14
- }
15
- export async function runCreateIssue(opts, args) {
16
- const { date, slug, title, type, source } = args;
17
- if (!date || !slug || !title) {
18
- console.error('Usage: create issue --date YYYY-MM-DD --slug <slug> --title <title> [--type disruption|maintenance|infra] [--source <source>]');
19
- return 1;
20
- }
21
- const dateMatch = /^(\d{4})-(\d{2})-(\d{2})$/.exec(date);
22
- if (!dateMatch) {
23
- console.error('Invalid date format. Use YYYY-MM-DD.');
24
- return 1;
25
- }
26
- const issueId = `${date}-${slug}`;
27
- const issueType = (type && IssueTypeSchema.safeParse(type).success ? type : 'disruption');
28
- const issue = {
29
- id: issueId,
30
- type: issueType,
31
- title: translationsFromEn(title),
32
- titleMeta: { source: source ?? 'cli' },
33
- };
34
- if (opts.dryRun) {
35
- console.log('Would create:', JSON.stringify(issue, null, 2));
36
- return 0;
37
- }
38
- const store = new FileWriteStore(opts.dataDir);
39
- const writer = new MRTDownWriter({ store });
40
- writer.issues.create(issue);
41
- console.log(`Created issue: ${join(opts.dataDir, 'issue', dateMatch[1], dateMatch[2], issueId)}`);
42
- return 0;
43
- }
44
- export async function runCreateTown(opts, args) {
45
- if (!args.id || !args.name) {
46
- console.error('Usage: create town --id <id> --name <name>');
47
- return 1;
48
- }
49
- const town = {
50
- id: args.id,
51
- name: translationsFromEn(args.name),
52
- };
53
- if (opts.dryRun) {
54
- console.log('Would create:', JSON.stringify(town, null, 2));
55
- return 0;
56
- }
57
- const store = new FileWriteStore(opts.dataDir);
58
- const writer = new MRTDownWriter({ store });
59
- writer.towns.create(town);
60
- console.log(`Created town: ${join(opts.dataDir, 'town', `${town.id}.json`)}`);
61
- return 0;
62
- }
63
- export async function runCreateLandmark(opts, args) {
64
- if (!args.id || !args.name) {
65
- console.error('Usage: create landmark --id <id> --name <name>');
66
- return 1;
67
- }
68
- const landmark = {
69
- id: args.id,
70
- name: translationsFromEn(args.name),
71
- };
72
- if (opts.dryRun) {
73
- console.log('Would create:', JSON.stringify(landmark, null, 2));
74
- return 0;
75
- }
76
- const store = new FileWriteStore(opts.dataDir);
77
- const writer = new MRTDownWriter({ store });
78
- writer.landmarks.create(landmark);
79
- console.log(`Created landmark: ${join(opts.dataDir, 'landmark', `${landmark.id}.json`)}`);
80
- return 0;
81
- }
82
- export async function runCreateOperator(opts, args) {
83
- if (!args.id || !args.name || !args.foundedAt) {
84
- console.error('Usage: create operator --id <id> --name <name> --founded-at YYYY-MM-DD [--url <url>]');
85
- return 1;
86
- }
87
- const operator = {
88
- id: args.id,
89
- name: translationsFromEn(args.name),
90
- foundedAt: args.foundedAt,
91
- url: args.url ?? null,
92
- };
93
- if (opts.dryRun) {
94
- console.log('Would create:', JSON.stringify(operator, null, 2));
95
- return 0;
96
- }
97
- const store = new FileWriteStore(opts.dataDir);
98
- const writer = new MRTDownWriter({ store });
99
- writer.operators.create(operator);
100
- console.log(`Created operator: ${join(opts.dataDir, 'operator', `${operator.id}.json`)}`);
101
- return 0;
102
- }
103
- async function readStdin() {
104
- const rl = createInterface({ input: process.stdin });
105
- const chunks = [];
106
- for await (const line of rl) {
107
- chunks.push(line);
108
- }
109
- return chunks.join('\n');
110
- }
111
- export async function runCreateStation(opts, args) {
112
- let json;
113
- if (opts.stdin) {
114
- const raw = await readStdin();
115
- json = JSON.parse(raw);
116
- }
117
- else {
118
- const file = args.stdinFile ?? args.file;
119
- if (file) {
120
- const raw = await readFile(file, 'utf-8');
121
- json = JSON.parse(raw);
122
- }
123
- else {
124
- console.error('Usage: create station --stdin < JSON | create station --file <path>');
125
- return 1;
126
- }
127
- }
128
- if (opts.dryRun) {
129
- console.log('Would create station:', JSON.stringify(json, null, 2));
130
- return 0;
131
- }
132
- const store = new FileWriteStore(opts.dataDir);
133
- const writer = new MRTDownWriter({ store });
134
- writer.stations.create(json);
135
- return 0;
136
- }
137
- export async function runCreateLine(opts, args) {
138
- let json;
139
- if (opts.stdin) {
140
- const raw = await readStdin();
141
- json = JSON.parse(raw);
142
- }
143
- else {
144
- const file = args.stdinFile ?? args.file;
145
- if (file) {
146
- const raw = await readFile(file, 'utf-8');
147
- json = JSON.parse(raw);
148
- }
149
- else {
150
- console.error('Usage: create line --stdin < JSON | create line --file <path>');
151
- return 1;
152
- }
153
- }
154
- if (opts.dryRun) {
155
- console.log('Would create line:', JSON.stringify(json, null, 2));
156
- return 0;
157
- }
158
- const store = new FileWriteStore(opts.dataDir);
159
- const writer = new MRTDownWriter({ store });
160
- writer.lines.create(json);
161
- return 0;
162
- }
163
- export async function runCreateService(opts, args) {
164
- let json;
165
- if (opts.stdin) {
166
- const raw = await readStdin();
167
- json = JSON.parse(raw);
168
- }
169
- else {
170
- const file = args.stdinFile ?? args.file;
171
- if (file) {
172
- const raw = await readFile(file, 'utf-8');
173
- json = JSON.parse(raw);
174
- }
175
- else {
176
- console.error('Usage: create service --stdin < JSON | create service --file <path>');
177
- return 1;
178
- }
179
- }
180
- if (opts.dryRun) {
181
- console.log('Would create service:', JSON.stringify(json, null, 2));
182
- return 0;
183
- }
184
- const store = new FileWriteStore(opts.dataDir);
185
- const writer = new MRTDownWriter({ store });
186
- writer.services.create(json);
187
- return 0;
188
- }
189
- //# sourceMappingURL=create.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"create.js","sourceRoot":"/","sources":["cli/commands/create.ts"],"names":[],"mappings":"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","sourcesContent":["import { readFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport { createInterface } from 'node:readline';\nimport type { IssueType } from '../../schema/issue/issueType.js';\nimport { IssueTypeSchema } from '../../schema/issue/issueType.js';\nimport { FileWriteStore } from '../../write/common/FileWriteStore.js';\nimport { MRTDownWriter } from '../../write/MRTDownWriter.js';\n\ntype CreateOptions = {\n dataDir: string;\n dryRun?: boolean;\n stdin?: boolean;\n};\n\nfunction translationsFromEn(en: string) {\n return {\n 'en-SG': en,\n 'zh-Hans': null,\n ms: null,\n ta: null,\n };\n}\n\nexport async function runCreateIssue(\n opts: CreateOptions,\n args: {\n date?: string;\n slug?: string;\n title?: string;\n type?: string;\n source?: string;\n },\n): Promise<number> {\n const { date, slug, title, type, source } = args;\n if (!date || !slug || !title) {\n console.error(\n 'Usage: create issue --date YYYY-MM-DD --slug <slug> --title <title> [--type disruption|maintenance|infra] [--source <source>]',\n );\n return 1;\n }\n\n const dateMatch = /^(\\d{4})-(\\d{2})-(\\d{2})$/.exec(date);\n if (!dateMatch) {\n console.error('Invalid date format. Use YYYY-MM-DD.');\n return 1;\n }\n\n const issueId = `${date}-${slug}`;\n const issueType = (\n type && IssueTypeSchema.safeParse(type).success ? type : 'disruption'\n ) as IssueType;\n\n const issue = {\n id: issueId,\n type: issueType,\n title: translationsFromEn(title),\n titleMeta: { source: source ?? 'cli' },\n };\n\n if (opts.dryRun) {\n console.log('Would create:', JSON.stringify(issue, null, 2));\n return 0;\n }\n\n const store = new FileWriteStore(opts.dataDir);\n const writer = new MRTDownWriter({ store });\n writer.issues.create(issue);\n console.log(\n `Created issue: ${join(opts.dataDir, 'issue', dateMatch[1], dateMatch[2], issueId)}`,\n );\n return 0;\n}\n\nexport async function runCreateTown(\n opts: CreateOptions,\n args: { id?: string; name?: string },\n): Promise<number> {\n if (!args.id || !args.name) {\n console.error('Usage: create town --id <id> --name <name>');\n return 1;\n }\n\n const town = {\n id: args.id,\n name: translationsFromEn(args.name),\n };\n\n if (opts.dryRun) {\n console.log('Would create:', JSON.stringify(town, null, 2));\n return 0;\n }\n\n const store = new FileWriteStore(opts.dataDir);\n const writer = new MRTDownWriter({ store });\n writer.towns.create(town);\n console.log(`Created town: ${join(opts.dataDir, 'town', `${town.id}.json`)}`);\n return 0;\n}\n\nexport async function runCreateLandmark(\n opts: CreateOptions,\n args: { id?: string; name?: string },\n): Promise<number> {\n if (!args.id || !args.name) {\n console.error('Usage: create landmark --id <id> --name <name>');\n return 1;\n }\n\n const landmark = {\n id: args.id,\n name: translationsFromEn(args.name),\n };\n\n if (opts.dryRun) {\n console.log('Would create:', JSON.stringify(landmark, null, 2));\n return 0;\n }\n\n const store = new FileWriteStore(opts.dataDir);\n const writer = new MRTDownWriter({ store });\n writer.landmarks.create(landmark);\n console.log(\n `Created landmark: ${join(opts.dataDir, 'landmark', `${landmark.id}.json`)}`,\n );\n return 0;\n}\n\nexport async function runCreateOperator(\n opts: CreateOptions,\n args: { id?: string; name?: string; foundedAt?: string; url?: string },\n): Promise<number> {\n if (!args.id || !args.name || !args.foundedAt) {\n console.error(\n 'Usage: create operator --id <id> --name <name> --founded-at YYYY-MM-DD [--url <url>]',\n );\n return 1;\n }\n\n const operator = {\n id: args.id,\n name: translationsFromEn(args.name),\n foundedAt: args.foundedAt,\n url: args.url ?? null,\n };\n\n if (opts.dryRun) {\n console.log('Would create:', JSON.stringify(operator, null, 2));\n return 0;\n }\n\n const store = new FileWriteStore(opts.dataDir);\n const writer = new MRTDownWriter({ store });\n writer.operators.create(operator);\n console.log(\n `Created operator: ${join(opts.dataDir, 'operator', `${operator.id}.json`)}`,\n );\n return 0;\n}\n\nasync function readStdin(): Promise<string> {\n const rl = createInterface({ input: process.stdin });\n const chunks: string[] = [];\n for await (const line of rl) {\n chunks.push(line);\n }\n return chunks.join('\\n');\n}\n\nexport async function runCreateStation(\n opts: CreateOptions,\n args: Record<string, string | undefined>,\n): Promise<number> {\n let json: unknown;\n if (opts.stdin) {\n const raw = await readStdin();\n json = JSON.parse(raw);\n } else {\n const file = args.stdinFile ?? args.file;\n if (file) {\n const raw = await readFile(file, 'utf-8');\n json = JSON.parse(raw);\n } else {\n console.error(\n 'Usage: create station --stdin < JSON | create station --file <path>',\n );\n return 1;\n }\n }\n\n if (opts.dryRun) {\n console.log('Would create station:', JSON.stringify(json, null, 2));\n return 0;\n }\n\n const store = new FileWriteStore(opts.dataDir);\n const writer = new MRTDownWriter({ store });\n writer.stations.create(json as Parameters<typeof writer.stations.create>[0]);\n return 0;\n}\n\nexport async function runCreateLine(\n opts: CreateOptions,\n args: Record<string, string | undefined>,\n): Promise<number> {\n let json: unknown;\n if (opts.stdin) {\n const raw = await readStdin();\n json = JSON.parse(raw);\n } else {\n const file = args.stdinFile ?? args.file;\n if (file) {\n const raw = await readFile(file, 'utf-8');\n json = JSON.parse(raw);\n } else {\n console.error(\n 'Usage: create line --stdin < JSON | create line --file <path>',\n );\n return 1;\n }\n }\n\n if (opts.dryRun) {\n console.log('Would create line:', JSON.stringify(json, null, 2));\n return 0;\n }\n\n const store = new FileWriteStore(opts.dataDir);\n const writer = new MRTDownWriter({ store });\n writer.lines.create(json as Parameters<typeof writer.lines.create>[0]);\n return 0;\n}\n\nexport async function runCreateService(\n opts: CreateOptions,\n args: Record<string, string | undefined>,\n): Promise<number> {\n let json: unknown;\n if (opts.stdin) {\n const raw = await readStdin();\n json = JSON.parse(raw);\n } else {\n const file = args.stdinFile ?? args.file;\n if (file) {\n const raw = await readFile(file, 'utf-8');\n json = JSON.parse(raw);\n } else {\n console.error(\n 'Usage: create service --stdin < JSON | create service --file <path>',\n );\n return 1;\n }\n }\n\n if (opts.dryRun) {\n console.log('Would create service:', JSON.stringify(json, null, 2));\n return 0;\n }\n\n const store = new FileWriteStore(opts.dataDir);\n const writer = new MRTDownWriter({ store });\n writer.services.create(json as Parameters<typeof writer.services.create>[0]);\n return 0;\n}\n"]}
@@ -1,6 +0,0 @@
1
- export type ListOptions = {
2
- dataDir: string;
3
- entity: 'issue' | 'town' | 'landmark' | 'operator' | 'station' | 'line' | 'service';
4
- json?: boolean;
5
- };
6
- export declare function runList(opts: ListOptions): number;
@@ -1,106 +0,0 @@
1
- import { FileStore } from '../../repo/common/FileStore.js';
2
- import { MRTDownRepository } from '../../repo/MRTDownRepository.js';
3
- function nameEn(item) {
4
- return item.name?.['en-SG'] ?? '—';
5
- }
6
- export function runList(opts) {
7
- const store = new FileStore(opts.dataDir);
8
- const repo = new MRTDownRepository({ store });
9
- switch (opts.entity) {
10
- case 'issue': {
11
- const bundles = repo.issues.list();
12
- if (opts.json) {
13
- console.log(JSON.stringify(bundles.map((b) => ({
14
- id: b.issue.id,
15
- type: b.issue.type,
16
- title: b.issue.title['en-SG'],
17
- })), null, 2));
18
- }
19
- else {
20
- for (const b of bundles) {
21
- console.log(`${b.issue.id} ${b.issue.title['en-SG'] ?? b.issue.id}`);
22
- }
23
- }
24
- break;
25
- }
26
- case 'town': {
27
- const items = repo.towns.list();
28
- if (opts.json) {
29
- console.log(JSON.stringify(items, null, 2));
30
- }
31
- else {
32
- for (const item of items) {
33
- console.log(`${item.id} ${nameEn(item)}`);
34
- }
35
- }
36
- break;
37
- }
38
- case 'landmark': {
39
- const items = repo.landmarks.list();
40
- if (opts.json) {
41
- console.log(JSON.stringify(items, null, 2));
42
- }
43
- else {
44
- for (const item of items) {
45
- console.log(`${item.id} ${nameEn(item)}`);
46
- }
47
- }
48
- break;
49
- }
50
- case 'operator': {
51
- const items = repo.operators.list();
52
- if (opts.json) {
53
- console.log(JSON.stringify(items, null, 2));
54
- }
55
- else {
56
- for (const item of items) {
57
- console.log(`${item.id} ${nameEn(item)}`);
58
- }
59
- }
60
- break;
61
- }
62
- case 'station': {
63
- const items = repo.stations.list();
64
- if (opts.json) {
65
- console.log(JSON.stringify(items, null, 2));
66
- }
67
- else {
68
- for (const item of items) {
69
- console.log(`${item.id} ${nameEn(item)}`);
70
- }
71
- }
72
- break;
73
- }
74
- case 'line': {
75
- const items = repo.lines.list();
76
- if (opts.json) {
77
- console.log(JSON.stringify(items, null, 2));
78
- }
79
- else {
80
- for (const item of items) {
81
- console.log(`${item.id} ${nameEn(item)} ${item.type}`);
82
- }
83
- }
84
- break;
85
- }
86
- case 'service': {
87
- const items = repo.services.list();
88
- if (opts.json) {
89
- console.log(JSON.stringify(items, null, 2));
90
- }
91
- else {
92
- for (const item of items) {
93
- console.log(`${item.id} ${nameEn(item)} ${item.lineId}`);
94
- }
95
- }
96
- break;
97
- }
98
- default: {
99
- const _ = opts.entity;
100
- console.error(`Unknown entity: ${opts.entity}`);
101
- return 1;
102
- }
103
- }
104
- return 0;
105
- }
106
- //# sourceMappingURL=list.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"list.js","sourceRoot":"/","sources":["cli/commands/list.ts"],"names":[],"mappings":"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","sourcesContent":["import { FileStore } from '../../repo/common/FileStore.js';\nimport { MRTDownRepository } from '../../repo/MRTDownRepository.js';\n\nexport type ListOptions = {\n dataDir: string;\n entity:\n | 'issue'\n | 'town'\n | 'landmark'\n | 'operator'\n | 'station'\n | 'line'\n | 'service';\n json?: boolean;\n};\n\nfunction nameEn(item: { name?: { 'en-SG'?: string } }): string {\n return item.name?.['en-SG'] ?? '—';\n}\n\nexport function runList(opts: ListOptions): number {\n const store = new FileStore(opts.dataDir);\n const repo = new MRTDownRepository({ store });\n\n switch (opts.entity) {\n case 'issue': {\n const bundles = repo.issues.list();\n if (opts.json) {\n console.log(\n JSON.stringify(\n bundles.map((b) => ({\n id: b.issue.id,\n type: b.issue.type,\n title: b.issue.title['en-SG'],\n })),\n null,\n 2,\n ),\n );\n } else {\n for (const b of bundles) {\n console.log(`${b.issue.id} ${b.issue.title['en-SG'] ?? b.issue.id}`);\n }\n }\n break;\n }\n case 'town': {\n const items = repo.towns.list();\n if (opts.json) {\n console.log(JSON.stringify(items, null, 2));\n } else {\n for (const item of items) {\n console.log(`${item.id} ${nameEn(item)}`);\n }\n }\n break;\n }\n case 'landmark': {\n const items = repo.landmarks.list();\n if (opts.json) {\n console.log(JSON.stringify(items, null, 2));\n } else {\n for (const item of items) {\n console.log(`${item.id} ${nameEn(item)}`);\n }\n }\n break;\n }\n case 'operator': {\n const items = repo.operators.list();\n if (opts.json) {\n console.log(JSON.stringify(items, null, 2));\n } else {\n for (const item of items) {\n console.log(`${item.id} ${nameEn(item)}`);\n }\n }\n break;\n }\n case 'station': {\n const items = repo.stations.list();\n if (opts.json) {\n console.log(JSON.stringify(items, null, 2));\n } else {\n for (const item of items) {\n console.log(`${item.id} ${nameEn(item)}`);\n }\n }\n break;\n }\n case 'line': {\n const items = repo.lines.list();\n if (opts.json) {\n console.log(JSON.stringify(items, null, 2));\n } else {\n for (const item of items) {\n console.log(`${item.id} ${nameEn(item)} ${item.type}`);\n }\n }\n break;\n }\n case 'service': {\n const items = repo.services.list();\n if (opts.json) {\n console.log(JSON.stringify(items, null, 2));\n } else {\n for (const item of items) {\n console.log(`${item.id} ${nameEn(item)} ${item.lineId}`);\n }\n }\n break;\n }\n default: {\n const _: never = opts.entity;\n console.error(`Unknown entity: ${opts.entity}`);\n return 1;\n }\n }\n\n return 0;\n}\n"]}
@@ -1,6 +0,0 @@
1
- export type ShowIssueOptions = {
2
- dataDir: string;
3
- issueId: string;
4
- json?: boolean;
5
- };
6
- export declare function runShowIssue(opts: ShowIssueOptions): number;
@@ -1,156 +0,0 @@
1
- import { DateTime } from 'luxon';
2
- import { FileStore } from '../../repo/common/FileStore.js';
3
- import { deriveCurrentState } from '../../repo/issue/helpers/deriveCurrentState.js';
4
- import { IssueRepository } from '../../repo/issue/IssueRepository.js';
5
- import { resolvePeriods, } from '../../helpers/resolvePeriods.js';
6
- function formatScope(scope) {
7
- switch (scope.type) {
8
- case 'service.whole':
9
- return 'whole line';
10
- case 'service.segment':
11
- return `${scope.fromStationId} → ${scope.toStationId}`;
12
- case 'service.point':
13
- return scope.stationId ?? '?';
14
- default:
15
- return JSON.stringify(scope);
16
- }
17
- }
18
- function formatEffect(effect) {
19
- if (!effect)
20
- return '—';
21
- if (effect.kind === 'delay') {
22
- return effect.duration ? `delay (${effect.duration})` : 'delay';
23
- }
24
- return effect.kind;
25
- }
26
- function formatPeriod(period) {
27
- const start = period.startAt;
28
- const end = period.endAtResolved ?? period.endAt ?? 'ongoing';
29
- let suffix = '';
30
- if (period.endAtSource === 'inferred' && period.endAtReason) {
31
- suffix = ` (inferred: ${period.endAtReason})`;
32
- }
33
- return `${start} → ${end}${suffix}`;
34
- }
35
- const MODES = ['canonical', 'operational'];
36
- function buildResolveMode(mode, evidence) {
37
- switch (mode) {
38
- case 'canonical':
39
- return { kind: 'canonical' };
40
- case 'operational': {
41
- const lastEvidenceAt = evidence.length > 0
42
- ? evidence.reduce((latest, e) => (e.ts > latest ? e.ts : latest), evidence[0].ts)
43
- : null;
44
- return { kind: 'operational', lastEvidenceAt };
45
- }
46
- }
47
- }
48
- function resolvePeriodsByMode(periods, asOf, evidence) {
49
- const result = {};
50
- for (const mode of MODES) {
51
- result[mode] =
52
- periods.length > 0
53
- ? resolvePeriods({
54
- periods,
55
- asOf,
56
- mode: buildResolveMode(mode, evidence),
57
- })
58
- : [];
59
- }
60
- return result;
61
- }
62
- export function runShowIssue(opts) {
63
- const store = new FileStore(opts.dataDir);
64
- const repo = new IssueRepository(store);
65
- const bundle = repo.get(opts.issueId);
66
- if (!bundle) {
67
- console.error(`Issue not found: ${opts.issueId}`);
68
- return 1;
69
- }
70
- const state = deriveCurrentState(bundle);
71
- const asOf = DateTime.now().toISO() ?? '';
72
- const resolvedServices = Object.fromEntries(Object.entries(state.services).map(([key, svc]) => [
73
- key,
74
- {
75
- ...svc,
76
- periodsByMode: resolvePeriodsByMode(svc.periods, asOf, bundle.evidence),
77
- },
78
- ]));
79
- const resolvedFacilities = Object.fromEntries(Object.entries(state.facilities).map(([key, fac]) => [
80
- key,
81
- {
82
- ...fac,
83
- periodsByMode: resolvePeriodsByMode(fac.periods, asOf, bundle.evidence),
84
- },
85
- ]));
86
- if (opts.json) {
87
- const output = {
88
- issue: bundle.issue,
89
- evidenceCount: bundle.evidence.length,
90
- impactEventCount: bundle.impactEvents.length,
91
- currentState: {
92
- ...state,
93
- services: resolvedServices,
94
- facilities: resolvedFacilities,
95
- },
96
- };
97
- console.log(JSON.stringify(output, null, 2));
98
- return 0;
99
- }
100
- // Human-readable output
101
- const { issue, evidence, impactEvents } = bundle;
102
- console.log(`\n${issue.title['en-SG'] ?? issue.id}`);
103
- console.log('─'.repeat(60));
104
- console.log(`ID: ${issue.id}`);
105
- console.log(`Type: ${issue.type}`);
106
- console.log(`Path: ${bundle.path}`);
107
- console.log(`Evidence: ${evidence.length} item(s)`);
108
- console.log(`Impact: ${impactEvents.length} event(s)`);
109
- console.log('');
110
- const hasServices = Object.keys(resolvedServices).length > 0;
111
- const hasFacilities = Object.keys(resolvedFacilities).length > 0;
112
- if (hasServices) {
113
- console.log('Current state — Services');
114
- console.log('─'.repeat(40));
115
- for (const [, svc] of Object.entries(resolvedServices)) {
116
- console.log(` ${svc.serviceId}`);
117
- console.log(` effect: ${formatEffect(svc.effect)}`);
118
- if (svc.scopes.length > 0) {
119
- console.log(` scopes: ${svc.scopes.map(formatScope).join('; ')}`);
120
- }
121
- for (const mode of MODES) {
122
- const periods = svc.periodsByMode[mode];
123
- if (periods.length > 0) {
124
- console.log(` periods (${mode}): ${periods.map(formatPeriod).join('; ')}`);
125
- }
126
- }
127
- if (svc.causes.length > 0) {
128
- console.log(` causes: ${svc.causes.join(', ')}`);
129
- }
130
- console.log('');
131
- }
132
- }
133
- if (hasFacilities) {
134
- console.log('Current state — Facilities');
135
- console.log('─'.repeat(40));
136
- for (const [, fac] of Object.entries(resolvedFacilities)) {
137
- console.log(` ${fac.stationId} (${fac.kind})`);
138
- console.log(` effect: ${formatEffect(fac.effect)}`);
139
- for (const mode of MODES) {
140
- const periods = fac.periodsByMode[mode];
141
- if (periods.length > 0) {
142
- console.log(` periods (${mode}): ${periods.map(formatPeriod).join('; ')}`);
143
- }
144
- }
145
- if (fac.causes.length > 0) {
146
- console.log(` causes: ${fac.causes.join(', ')}`);
147
- }
148
- console.log('');
149
- }
150
- }
151
- if (!hasServices && !hasFacilities) {
152
- console.log('Current state: (no services or facilities affected)');
153
- }
154
- return 0;
155
- }
156
- //# sourceMappingURL=show.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"show.js","sourceRoot":"/","sources":["cli/commands/show.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,gDAAgD,CAAC;AACpF,OAAO,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAEtE,OAAO,EAEL,cAAc,GACf,MAAM,iCAAiC,CAAC;AAQzC,SAAS,WAAW,CAAC,KAKpB;IACC,QAAQ,KAAK,CAAC,IAAI,EAAE,CAAC;QACnB,KAAK,eAAe;YAClB,OAAO,YAAY,CAAC;QACtB,KAAK,iBAAiB;YACpB,OAAO,GAAG,KAAK,CAAC,aAAa,MAAM,KAAK,CAAC,WAAW,EAAE,CAAC;QACzD,KAAK,eAAe;YAClB,OAAO,KAAK,CAAC,SAAS,IAAI,GAAG,CAAC;QAChC;YACE,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;IACjC,CAAC;AACH,CAAC;AAED,SAAS,YAAY,CACnB,MAAyD;IAEzD,IAAI,CAAC,MAAM;QAAE,OAAO,GAAG,CAAC;IACxB,IAAI,MAAM,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;QAC5B,OAAO,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,MAAM,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC;IAClE,CAAC;IACD,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC;AAUD,SAAS,YAAY,CAAC,MAAsB;IAC1C,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC;IAC7B,MAAM,GAAG,GAAG,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,KAAK,IAAI,SAAS,CAAC;IAC9D,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,MAAM,CAAC,WAAW,KAAK,UAAU,IAAI,MAAM,CAAC,WAAW,EAAE,CAAC;QAC5D,MAAM,GAAG,eAAe,MAAM,CAAC,WAAW,GAAG,CAAC;IAChD,CAAC;IACD,OAAO,GAAG,KAAK,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC;AACtC,CAAC;AAED,MAAM,KAAK,GAAG,CAAC,WAAW,EAAE,aAAa,CAAU,CAAC;AAEpD,SAAS,gBAAgB,CACvB,IAA4B,EAC5B,QAA0B;IAE1B,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,WAAW;YACd,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;QAC/B,KAAK,aAAa,CAAC,CAAC,CAAC;YACnB,MAAM,cAAc,GAClB,QAAQ,CAAC,MAAM,GAAG,CAAC;gBACjB,CAAC,CAAC,QAAQ,CAAC,MAAM,CACb,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,EAC9C,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CACf;gBACH,CAAC,CAAC,IAAI,CAAC;YACX,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,cAAc,EAAE,CAAC;QACjD,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,oBAAoB,CAC3B,OAAiB,EACjB,IAAY,EACZ,QAA0B;IAE1B,MAAM,MAAM,GAAG,EAAsD,CAAC;IACtE,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC;YACV,OAAO,CAAC,MAAM,GAAG,CAAC;gBAChB,CAAC,CAAC,cAAc,CAAC;oBACb,OAAO;oBACP,IAAI;oBACJ,IAAI,EAAE,gBAAgB,CAAC,IAAI,EAAE,QAAQ,CAAC;iBACvC,CAAC;gBACJ,CAAC,CAAC,EAAE,CAAC;IACX,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAsB;IACjD,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,IAAI,GAAG,IAAI,eAAe,CAAC,KAAK,CAAC,CAAC;IAExC,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,KAAK,CAAC,oBAAoB,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC;QAClD,OAAO,CAAC,CAAC;IACX,CAAC;IAED,MAAM,KAAK,GAAG,kBAAkB,CAAC,MAAM,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC;IAE1C,MAAM,gBAAgB,GAAG,MAAM,CAAC,WAAW,CACzC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;QACjD,GAAG;QACH;YACE,GAAG,GAAG;YACN,aAAa,EAAE,oBAAoB,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC;SACxE;KACF,CAAC,CACH,CAAC;IAEF,MAAM,kBAAkB,GAAG,MAAM,CAAC,WAAW,CAC3C,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC;QACnD,GAAG;QACH;YACE,GAAG,GAAG;YACN,aAAa,EAAE,oBAAoB,CAAC,GAAG,CAAC,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC;SACxE;KACF,CAAC,CACH,CAAC;IAEF,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,MAAM,GAAG;YACb,KAAK,EAAE,MAAM,CAAC,KAAK;YACnB,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,MAAM;YACrC,gBAAgB,EAAE,MAAM,CAAC,YAAY,CAAC,MAAM;YAC5C,YAAY,EAAE;gBACZ,GAAG,KAAK;gBACR,QAAQ,EAAE,gBAAgB;gBAC1B,UAAU,EAAE,kBAAkB;aAC/B;SACF,CAAC;QACF,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7C,OAAO,CAAC,CAAC;IACX,CAAC;IAED,wBAAwB;IACxB,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,MAAM,CAAC;IACjD,OAAO,CAAC,GAAG,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IACrD,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;IAC5B,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,WAAW,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;IACrC,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACtC,OAAO,CAAC,GAAG,CAAC,aAAa,QAAQ,CAAC,MAAM,UAAU,CAAC,CAAC;IACpD,OAAO,CAAC,GAAG,CAAC,YAAY,YAAY,CAAC,MAAM,WAAW,CAAC,CAAC;IACxD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAEhB,MAAM,WAAW,GAAG,MAAM,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IAC7D,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;IAEjE,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,0BAA0B,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5B,KAAK,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,gBAAgB,CAAC,EAAE,CAAC;YACvD,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,SAAS,EAAE,CAAC,CAAC;YAClC,OAAO,CAAC,GAAG,CAAC,gBAAgB,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACxD,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACxE,CAAC;YACD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,OAAO,GAAG,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;gBACxC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACvB,OAAO,CAAC,GAAG,CACT,gBAAgB,IAAI,MAAM,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACjE,CAAC;gBACJ,CAAC;YACH,CAAC;YACD,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACvD,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,IAAI,aAAa,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAC;QAC1C,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC;QAC5B,KAAK,MAAM,CAAC,EAAE,GAAG,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,CAAC;YACzD,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,SAAS,KAAK,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC;YAChD,OAAO,CAAC,GAAG,CAAC,gBAAgB,YAAY,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC;YACxD,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,MAAM,OAAO,GAAG,GAAG,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;gBACxC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACvB,OAAO,CAAC,GAAG,CACT,gBAAgB,IAAI,MAAM,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CACjE,CAAC;gBACJ,CAAC;YACH,CAAC;YACD,IAAI,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC1B,OAAO,CAAC,GAAG,CAAC,gBAAgB,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACvD,CAAC;YACD,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAClB,CAAC;IACH,CAAC;IAED,IAAI,CAAC,WAAW,IAAI,CAAC,aAAa,EAAE,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,qDAAqD,CAAC,CAAC;IACrE,CAAC;IAED,OAAO,CAAC,CAAC;AACX,CAAC","sourcesContent":["import { DateTime } from 'luxon';\nimport { FileStore } from '../../repo/common/FileStore.js';\nimport { deriveCurrentState } from '../../repo/issue/helpers/deriveCurrentState.js';\nimport { IssueRepository } from '../../repo/issue/IssueRepository.js';\nimport type { Period } from '../../schema/issue/period.js';\nimport {\n type ResolvePeriodsMode,\n resolvePeriods,\n} from '../../helpers/resolvePeriods.js';\n\nexport type ShowIssueOptions = {\n dataDir: string;\n issueId: string;\n json?: boolean;\n};\n\nfunction formatScope(scope: {\n type: string;\n fromStationId?: string;\n toStationId?: string;\n stationId?: string;\n}): string {\n switch (scope.type) {\n case 'service.whole':\n return 'whole line';\n case 'service.segment':\n return `${scope.fromStationId} → ${scope.toStationId}`;\n case 'service.point':\n return scope.stationId ?? '?';\n default:\n return JSON.stringify(scope);\n }\n}\n\nfunction formatEffect(\n effect: { kind: string; duration?: string | null } | null,\n): string {\n if (!effect) return '—';\n if (effect.kind === 'delay') {\n return effect.duration ? `delay (${effect.duration})` : 'delay';\n }\n return effect.kind;\n}\n\ntype ResolvedPeriod = {\n startAt: string;\n endAt: string | null;\n endAtResolved: string | null;\n endAtSource: 'fact' | 'inferred' | 'none';\n endAtReason?: 'crowd_decay' | 'evidence_timeout';\n};\n\nfunction formatPeriod(period: ResolvedPeriod): string {\n const start = period.startAt;\n const end = period.endAtResolved ?? period.endAt ?? 'ongoing';\n let suffix = '';\n if (period.endAtSource === 'inferred' && period.endAtReason) {\n suffix = ` (inferred: ${period.endAtReason})`;\n }\n return `${start} → ${end}${suffix}`;\n}\n\nconst MODES = ['canonical', 'operational'] as const;\n\nfunction buildResolveMode(\n mode: (typeof MODES)[number],\n evidence: { ts: string }[],\n): ResolvePeriodsMode {\n switch (mode) {\n case 'canonical':\n return { kind: 'canonical' };\n case 'operational': {\n const lastEvidenceAt =\n evidence.length > 0\n ? evidence.reduce<string>(\n (latest, e) => (e.ts > latest ? e.ts : latest),\n evidence[0].ts,\n )\n : null;\n return { kind: 'operational', lastEvidenceAt };\n }\n }\n}\n\nfunction resolvePeriodsByMode(\n periods: Period[],\n asOf: string,\n evidence: { ts: string }[],\n): Record<(typeof MODES)[number], ResolvedPeriod[]> {\n const result = {} as Record<(typeof MODES)[number], ResolvedPeriod[]>;\n for (const mode of MODES) {\n result[mode] =\n periods.length > 0\n ? resolvePeriods({\n periods,\n asOf,\n mode: buildResolveMode(mode, evidence),\n })\n : [];\n }\n return result;\n}\n\nexport function runShowIssue(opts: ShowIssueOptions): number {\n const store = new FileStore(opts.dataDir);\n const repo = new IssueRepository(store);\n\n const bundle = repo.get(opts.issueId);\n if (!bundle) {\n console.error(`Issue not found: ${opts.issueId}`);\n return 1;\n }\n\n const state = deriveCurrentState(bundle);\n const asOf = DateTime.now().toISO() ?? '';\n\n const resolvedServices = Object.fromEntries(\n Object.entries(state.services).map(([key, svc]) => [\n key,\n {\n ...svc,\n periodsByMode: resolvePeriodsByMode(svc.periods, asOf, bundle.evidence),\n },\n ]),\n );\n\n const resolvedFacilities = Object.fromEntries(\n Object.entries(state.facilities).map(([key, fac]) => [\n key,\n {\n ...fac,\n periodsByMode: resolvePeriodsByMode(fac.periods, asOf, bundle.evidence),\n },\n ]),\n );\n\n if (opts.json) {\n const output = {\n issue: bundle.issue,\n evidenceCount: bundle.evidence.length,\n impactEventCount: bundle.impactEvents.length,\n currentState: {\n ...state,\n services: resolvedServices,\n facilities: resolvedFacilities,\n },\n };\n console.log(JSON.stringify(output, null, 2));\n return 0;\n }\n\n // Human-readable output\n const { issue, evidence, impactEvents } = bundle;\n console.log(`\\n${issue.title['en-SG'] ?? issue.id}`);\n console.log('─'.repeat(60));\n console.log(`ID: ${issue.id}`);\n console.log(`Type: ${issue.type}`);\n console.log(`Path: ${bundle.path}`);\n console.log(`Evidence: ${evidence.length} item(s)`);\n console.log(`Impact: ${impactEvents.length} event(s)`);\n console.log('');\n\n const hasServices = Object.keys(resolvedServices).length > 0;\n const hasFacilities = Object.keys(resolvedFacilities).length > 0;\n\n if (hasServices) {\n console.log('Current state — Services');\n console.log('─'.repeat(40));\n for (const [, svc] of Object.entries(resolvedServices)) {\n console.log(` ${svc.serviceId}`);\n console.log(` effect: ${formatEffect(svc.effect)}`);\n if (svc.scopes.length > 0) {\n console.log(` scopes: ${svc.scopes.map(formatScope).join('; ')}`);\n }\n for (const mode of MODES) {\n const periods = svc.periodsByMode[mode];\n if (periods.length > 0) {\n console.log(\n ` periods (${mode}): ${periods.map(formatPeriod).join('; ')}`,\n );\n }\n }\n if (svc.causes.length > 0) {\n console.log(` causes: ${svc.causes.join(', ')}`);\n }\n console.log('');\n }\n }\n\n if (hasFacilities) {\n console.log('Current state — Facilities');\n console.log('─'.repeat(40));\n for (const [, fac] of Object.entries(resolvedFacilities)) {\n console.log(` ${fac.stationId} (${fac.kind})`);\n console.log(` effect: ${formatEffect(fac.effect)}`);\n for (const mode of MODES) {\n const periods = fac.periodsByMode[mode];\n if (periods.length > 0) {\n console.log(\n ` periods (${mode}): ${periods.map(formatPeriod).join('; ')}`,\n );\n }\n }\n if (fac.causes.length > 0) {\n console.log(` causes: ${fac.causes.join(', ')}`);\n }\n console.log('');\n }\n }\n\n if (!hasServices && !hasFacilities) {\n console.log('Current state: (no services or facilities affected)');\n }\n\n return 0;\n}\n"]}
@@ -1,6 +0,0 @@
1
- import { type ValidationScope } from '../../validators/index.js';
2
- export interface ValidateCliOptions {
3
- dataDir: string;
4
- scope?: ValidationScope[];
5
- }
6
- export declare function runValidate(opts: ValidateCliOptions): number;
@@ -1,19 +0,0 @@
1
- import { FileStore } from '../../repo/common/FileStore.js';
2
- import { validateAll } from '../../validators/index.js';
3
- export function runValidate(opts) {
4
- const store = new FileStore(opts.dataDir);
5
- const errors = validateAll(store, { scope: opts.scope });
6
- if (errors.length === 0) {
7
- console.log('All data files are valid.');
8
- return 0;
9
- }
10
- console.error(`\nFound ${errors.length} validation error(s):\n`);
11
- for (const err of errors) {
12
- const loc = err.line ? `${err.file}:${err.line}` : err.file;
13
- console.error(` ${loc}`);
14
- console.error(` ${err.message}`);
15
- console.error('');
16
- }
17
- return 1;
18
- }
19
- //# sourceMappingURL=validate.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"validate.js","sourceRoot":"/","sources":["cli/commands/validate.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,gCAAgC,CAAC;AAC3D,OAAO,EAAwB,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAO9E,MAAM,UAAU,WAAW,CAAC,IAAwB;IAClD,MAAM,KAAK,GAAG,IAAI,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC1C,MAAM,MAAM,GAAG,WAAW,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC;IAEzD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACzC,OAAO,CAAC,CAAC;IACX,CAAC;IAED,OAAO,CAAC,KAAK,CAAC,WAAW,MAAM,CAAC,MAAM,yBAAyB,CAAC,CAAC;IACjE,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,IAAI,IAAI,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC;QAC5D,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC;QAC1B,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;QACpC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACpB,CAAC;IACD,OAAO,CAAC,CAAC;AACX,CAAC","sourcesContent":["import { FileStore } from '../../repo/common/FileStore.js';\nimport { type ValidationScope, validateAll } from '../../validators/index.js';\n\nexport interface ValidateCliOptions {\n dataDir: string;\n scope?: ValidationScope[];\n}\n\nexport function runValidate(opts: ValidateCliOptions): number {\n const store = new FileStore(opts.dataDir);\n const errors = validateAll(store, { scope: opts.scope });\n\n if (errors.length === 0) {\n console.log('All data files are valid.');\n return 0;\n }\n\n console.error(`\\nFound ${errors.length} validation error(s):\\n`);\n for (const err of errors) {\n const loc = err.line ? `${err.file}:${err.line}` : err.file;\n console.error(` ${loc}`);\n console.error(` ${err.message}`);\n console.error('');\n }\n return 1;\n}\n"]}
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};