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

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 (140) hide show
  1. package/dist/cli/commands/create.d.ts +30 -0
  2. package/dist/cli/commands/create.js +189 -0
  3. package/dist/cli/commands/create.js.map +1 -0
  4. package/dist/cli/commands/list.d.ts +6 -0
  5. package/dist/cli/commands/list.js +106 -0
  6. package/dist/cli/commands/list.js.map +1 -0
  7. package/dist/cli/commands/show.d.ts +6 -0
  8. package/dist/cli/commands/show.js +156 -0
  9. package/dist/cli/commands/show.js.map +1 -0
  10. package/dist/cli/commands/validate.d.ts +6 -0
  11. package/dist/cli/commands/validate.js +19 -0
  12. package/dist/cli/commands/validate.js.map +1 -0
  13. package/dist/cli/index.d.ts +2 -0
  14. package/dist/cli/index.js +162 -0
  15. package/dist/cli/index.js.map +1 -0
  16. package/dist/helpers/keyForAffectedEntity.d.ts +1 -1
  17. package/dist/helpers/keyForAffectedEntity.js.map +1 -1
  18. package/dist/helpers/normalizeRecurringPeriod.d.ts +1 -1
  19. package/dist/helpers/normalizeRecurringPeriod.js +1 -1
  20. package/dist/helpers/normalizeRecurringPeriod.js.map +1 -1
  21. package/dist/helpers/normalizeRecurringPeriod.test.js.map +1 -1
  22. package/dist/helpers/resolvePeriods.d.ts +1 -1
  23. package/dist/helpers/resolvePeriods.js +1 -1
  24. package/dist/helpers/resolvePeriods.js.map +1 -1
  25. package/dist/helpers/resolvePeriods.test.js.map +1 -1
  26. package/dist/index.d.ts +25 -25
  27. package/dist/index.js +25 -25
  28. package/dist/index.js.map +1 -1
  29. package/dist/llm/client.d.ts +2 -0
  30. package/dist/llm/client.js +5 -0
  31. package/dist/llm/client.js.map +1 -0
  32. package/dist/llm/common/MemoryStore.d.ts +21 -0
  33. package/dist/llm/common/MemoryStore.js +100 -0
  34. package/dist/llm/common/MemoryStore.js.map +1 -0
  35. package/dist/llm/common/MemoryStore.test.d.ts +1 -0
  36. package/dist/llm/common/MemoryStore.test.js +225 -0
  37. package/dist/llm/common/MemoryStore.test.js.map +1 -0
  38. package/dist/llm/common/formatCurrentState.d.ts +10 -0
  39. package/dist/llm/common/formatCurrentState.js +342 -0
  40. package/dist/llm/common/formatCurrentState.js.map +1 -0
  41. package/dist/llm/common/tool.d.ts +32 -0
  42. package/dist/llm/common/tool.js +6 -0
  43. package/dist/llm/common/tool.js.map +1 -0
  44. package/dist/llm/functions/extractClaimsFromNewEvidence/eval.test.d.ts +1 -0
  45. package/dist/llm/functions/extractClaimsFromNewEvidence/eval.test.js +433 -0
  46. package/dist/llm/functions/extractClaimsFromNewEvidence/eval.test.js.map +1 -0
  47. package/dist/llm/functions/extractClaimsFromNewEvidence/index.d.ts +18 -0
  48. package/dist/llm/functions/extractClaimsFromNewEvidence/index.js +153 -0
  49. package/dist/llm/functions/extractClaimsFromNewEvidence/index.js.map +1 -0
  50. package/dist/llm/functions/extractClaimsFromNewEvidence/prompt.d.ts +1 -0
  51. package/dist/llm/functions/extractClaimsFromNewEvidence/prompt.js +168 -0
  52. package/dist/llm/functions/extractClaimsFromNewEvidence/prompt.js.map +1 -0
  53. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindLinesTool.d.ts +19 -0
  54. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindLinesTool.js +65 -0
  55. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindLinesTool.js.map +1 -0
  56. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindServicesTool.d.ts +21 -0
  57. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindServicesTool.js +115 -0
  58. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindServicesTool.js.map +1 -0
  59. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindStationsTool.d.ts +24 -0
  60. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindStationsTool.js +110 -0
  61. package/dist/llm/functions/extractClaimsFromNewEvidence/tools/FindStationsTool.js.map +1 -0
  62. package/dist/llm/functions/generateIssueTitleAndSlug/index.d.ts +14 -0
  63. package/dist/llm/functions/generateIssueTitleAndSlug/index.js +38 -0
  64. package/dist/llm/functions/generateIssueTitleAndSlug/index.js.map +1 -0
  65. package/dist/llm/functions/generateIssueTitleAndSlug/prompt.d.ts +1 -0
  66. package/dist/llm/functions/generateIssueTitleAndSlug/prompt.js +23 -0
  67. package/dist/llm/functions/generateIssueTitleAndSlug/prompt.js.map +1 -0
  68. package/dist/llm/functions/translate/index.d.ts +1 -0
  69. package/dist/llm/functions/translate/index.js +59 -0
  70. package/dist/llm/functions/translate/index.js.map +1 -0
  71. package/dist/llm/functions/triageNewEvidence/eval.test.d.ts +1 -0
  72. package/dist/llm/functions/triageNewEvidence/eval.test.js +139 -0
  73. package/dist/llm/functions/triageNewEvidence/eval.test.js.map +1 -0
  74. package/dist/llm/functions/triageNewEvidence/index.d.ts +37 -0
  75. package/dist/llm/functions/triageNewEvidence/index.js +121 -0
  76. package/dist/llm/functions/triageNewEvidence/index.js.map +1 -0
  77. package/dist/llm/functions/triageNewEvidence/prompt.d.ts +1 -0
  78. package/dist/llm/functions/triageNewEvidence/prompt.js +60 -0
  79. package/dist/llm/functions/triageNewEvidence/prompt.js.map +1 -0
  80. package/dist/llm/functions/triageNewEvidence/tools/FindIssuesTool.d.ts +19 -0
  81. package/dist/llm/functions/triageNewEvidence/tools/FindIssuesTool.js +65 -0
  82. package/dist/llm/functions/triageNewEvidence/tools/FindIssuesTool.js.map +1 -0
  83. package/dist/llm/functions/triageNewEvidence/tools/GetIssueTool.d.ts +19 -0
  84. package/dist/llm/functions/triageNewEvidence/tools/GetIssueTool.js +37 -0
  85. package/dist/llm/functions/triageNewEvidence/tools/GetIssueTool.js.map +1 -0
  86. package/dist/repo/issue/IssueRepository.d.ts +1 -1
  87. package/dist/repo/issue/IssueRepository.js +3 -3
  88. package/dist/repo/issue/IssueRepository.js.map +1 -1
  89. package/dist/repo/issue/helpers/deriveCurrentState.d.ts +6 -6
  90. package/dist/repo/issue/helpers/deriveCurrentState.js +1 -1
  91. package/dist/repo/issue/helpers/deriveCurrentState.js.map +1 -1
  92. package/dist/repo/issue/helpers/deriveCurrentState.test.js.map +1 -1
  93. package/dist/schema/issue/evidence.js +1 -1
  94. package/dist/schema/issue/evidence.js.map +1 -1
  95. package/dist/schema/issue/issue.js +1 -1
  96. package/dist/schema/issue/issue.js.map +1 -1
  97. package/dist/scripts/ingestViaWebhook.d.ts +1 -0
  98. package/dist/scripts/ingestViaWebhook.js +9 -0
  99. package/dist/scripts/ingestViaWebhook.js.map +1 -0
  100. package/dist/util/ingestContent/helpers/getSlugDateTimeFromClaims.d.ts +1 -1
  101. package/dist/util/ingestContent/helpers/getSlugDateTimeFromClaims.js +1 -1
  102. package/dist/util/ingestContent/helpers/getSlugDateTimeFromClaims.js.map +1 -1
  103. package/dist/util/ingestContent/index.js +9 -9
  104. package/dist/util/ingestContent/index.js.map +1 -1
  105. package/dist/validators/buildContext.d.ts +7 -0
  106. package/dist/validators/buildContext.js +164 -0
  107. package/dist/validators/buildContext.js.map +1 -0
  108. package/dist/validators/index.d.ts +17 -0
  109. package/dist/validators/index.js +58 -0
  110. package/dist/validators/index.js.map +1 -0
  111. package/dist/validators/issue.d.ts +13 -0
  112. package/dist/validators/issue.js +220 -0
  113. package/dist/validators/issue.js.map +1 -0
  114. package/dist/validators/landmark.d.ts +7 -0
  115. package/dist/validators/landmark.js +43 -0
  116. package/dist/validators/landmark.js.map +1 -0
  117. package/dist/validators/line.d.ts +8 -0
  118. package/dist/validators/line.js +87 -0
  119. package/dist/validators/line.js.map +1 -0
  120. package/dist/validators/operator.d.ts +7 -0
  121. package/dist/validators/operator.js +43 -0
  122. package/dist/validators/operator.js.map +1 -0
  123. package/dist/validators/service.d.ts +8 -0
  124. package/dist/validators/service.js +87 -0
  125. package/dist/validators/service.js.map +1 -0
  126. package/dist/validators/station.d.ts +8 -0
  127. package/dist/validators/station.js +93 -0
  128. package/dist/validators/station.js.map +1 -0
  129. package/dist/validators/town.d.ts +7 -0
  130. package/dist/validators/town.js +43 -0
  131. package/dist/validators/town.js.map +1 -0
  132. package/dist/validators/types.d.ts +19 -0
  133. package/dist/validators/types.js +2 -0
  134. package/dist/validators/types.js.map +1 -0
  135. package/dist/validators/utils.d.ts +2 -0
  136. package/dist/validators/utils.js +9 -0
  137. package/dist/validators/utils.js.map +1 -0
  138. package/dist/write/issue/IssueWriter.d.ts +3 -3
  139. package/dist/write/issue/IssueWriter.js.map +1 -1
  140. package/package.json +2 -7
@@ -0,0 +1,43 @@
1
+ import { join } from 'node:path';
2
+ import { DIR_LANDMARK } from '../constants.js';
3
+ import { LandmarkSchema } from '../schema/Landmark.js';
4
+ import { loadJson } from './utils.js';
5
+ export function validateLandmarkSchema(data) {
6
+ const result = LandmarkSchema.safeParse(data);
7
+ if (result.success)
8
+ return [];
9
+ return result.error.issues.map((i) => ({
10
+ file: '',
11
+ message: `${i.path.length > 0 ? i.path.join('.') : 'root'}: ${i.message}`,
12
+ }));
13
+ }
14
+ export function validateLandmarks(store) {
15
+ const errors = [];
16
+ try {
17
+ const files = store.listDir(DIR_LANDMARK);
18
+ for (const file of files) {
19
+ if (!file.endsWith('.json'))
20
+ continue;
21
+ const relPath = join(DIR_LANDMARK, file);
22
+ const raw = loadJson(store, relPath);
23
+ if (raw === null) {
24
+ errors.push({ file: relPath, message: 'Failed to parse JSON' });
25
+ continue;
26
+ }
27
+ const schemaErrs = validateLandmarkSchema(raw);
28
+ for (const e of schemaErrs) {
29
+ errors.push({ ...e, file: e.file || relPath });
30
+ }
31
+ }
32
+ }
33
+ catch (err) {
34
+ if (err.code !== 'ENOENT') {
35
+ errors.push({
36
+ file: DIR_LANDMARK,
37
+ message: err instanceof Error ? err.message : String(err),
38
+ });
39
+ }
40
+ }
41
+ return errors;
42
+ }
43
+ //# sourceMappingURL=landmark.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"landmark.js","sourceRoot":"/","sources":["validators/landmark.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAE/C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,UAAU,sBAAsB,CACpC,IAAa;IAEb,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAC9B,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACrC,IAAI,EAAE,EAAE;QACR,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,EAAE;KAC1E,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,SAAS;YACtC,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;YACzC,MAAM,GAAG,GAAG,QAAQ,CAAU,KAAK,EAAE,OAAO,CAAC,CAAC;YAC9C,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBACjB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC,CAAC;gBAChE,SAAS;YACX,CAAC;YACD,MAAM,UAAU,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC;YAC/C,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;gBAC3B,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,YAAY;gBAClB,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aAC1D,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import { join } from 'node:path';\nimport { DIR_LANDMARK } from '../constants.js';\nimport type { IStore } from '../repo/common/store.js';\nimport { LandmarkSchema } from '../schema/Landmark.js';\nimport type { ValidationError } from './types.js';\nimport { loadJson } from './utils.js';\n\nexport function validateLandmarkSchema(\n data: unknown,\n): { file: string; message: string }[] {\n const result = LandmarkSchema.safeParse(data);\n if (result.success) return [];\n return result.error.issues.map((i) => ({\n file: '',\n message: `${i.path.length > 0 ? i.path.join('.') : 'root'}: ${i.message}`,\n }));\n}\n\nexport function validateLandmarks(store: IStore): ValidationError[] {\n const errors: ValidationError[] = [];\n try {\n const files = store.listDir(DIR_LANDMARK);\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n const relPath = join(DIR_LANDMARK, file);\n const raw = loadJson<unknown>(store, relPath);\n if (raw === null) {\n errors.push({ file: relPath, message: 'Failed to parse JSON' });\n continue;\n }\n const schemaErrs = validateLandmarkSchema(raw);\n for (const e of schemaErrs) {\n errors.push({ ...e, file: e.file || relPath });\n }\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n errors.push({\n file: DIR_LANDMARK,\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n return errors;\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import type z from 'zod';
2
+ import { LineSchema } from '../schema/Line.js';
3
+ import type { IStore } from '../repo/common/store.js';
4
+ import type { ValidationContext, ValidationError } from './types.js';
5
+ export declare function validateLineSchema(data: unknown): ValidationError[];
6
+ export declare function validateLineRelationships(data: z.infer<typeof LineSchema>, ctx: ValidationContext, file: string): ValidationError[];
7
+ export declare function validateLines(store: IStore): ValidationError[];
8
+ export declare function validateLinesRelationships(store: IStore, ctx?: ValidationContext): ValidationError[];
@@ -0,0 +1,87 @@
1
+ import { join } from 'node:path';
2
+ import { LineSchema } from '../schema/Line.js';
3
+ import { DIR_LINE } from '../constants.js';
4
+ import { loadJson } from './utils.js';
5
+ export function validateLineSchema(data) {
6
+ const result = LineSchema.safeParse(data);
7
+ if (result.success)
8
+ return [];
9
+ return result.error.issues.map((i) => ({
10
+ file: '',
11
+ message: `${i.path.length > 0 ? i.path.join('.') : 'root'}: ${i.message}`,
12
+ }));
13
+ }
14
+ export function validateLineRelationships(data, ctx, file) {
15
+ const errors = [];
16
+ for (const op of data.operators) {
17
+ if (!ctx.operatorIds.has(op.operatorId)) {
18
+ errors.push({
19
+ file,
20
+ message: `operators[].operatorId "${op.operatorId}" does not exist`,
21
+ });
22
+ }
23
+ }
24
+ for (const serviceId of data.serviceIds) {
25
+ if (!ctx.serviceIds.has(serviceId)) {
26
+ errors.push({
27
+ file,
28
+ message: `serviceIds: "${serviceId}" does not exist`,
29
+ });
30
+ }
31
+ }
32
+ return errors;
33
+ }
34
+ export function validateLines(store) {
35
+ const errors = [];
36
+ try {
37
+ const files = store.listDir(DIR_LINE);
38
+ for (const file of files) {
39
+ if (!file.endsWith('.json'))
40
+ continue;
41
+ const relPath = join(DIR_LINE, file);
42
+ const raw = loadJson(store, relPath);
43
+ if (raw === null) {
44
+ errors.push({ file: relPath, message: 'Failed to parse JSON' });
45
+ continue;
46
+ }
47
+ const schemaErrs = validateLineSchema(raw);
48
+ for (const e of schemaErrs) {
49
+ errors.push({ ...e, file: e.file || relPath });
50
+ }
51
+ }
52
+ }
53
+ catch (err) {
54
+ if (err.code !== 'ENOENT') {
55
+ errors.push({
56
+ file: DIR_LINE,
57
+ message: err instanceof Error ? err.message : String(err),
58
+ });
59
+ }
60
+ }
61
+ return errors;
62
+ }
63
+ export function validateLinesRelationships(store, ctx) {
64
+ if (!ctx)
65
+ return [];
66
+ const errors = [];
67
+ try {
68
+ const files = store.listDir(DIR_LINE);
69
+ for (const file of files) {
70
+ if (!file.endsWith('.json'))
71
+ continue;
72
+ const relPath = join(DIR_LINE, file);
73
+ const raw = loadJson(store, relPath);
74
+ if (raw === null)
75
+ continue;
76
+ const parsed = LineSchema.safeParse(raw);
77
+ if (parsed.success) {
78
+ errors.push(...validateLineRelationships(parsed.data, ctx, relPath));
79
+ }
80
+ }
81
+ }
82
+ catch {
83
+ // ignore
84
+ }
85
+ return errors;
86
+ }
87
+ //# sourceMappingURL=line.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"line.js","sourceRoot":"/","sources":["validators/line.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from 'node:path';\nimport type z from 'zod';\nimport { LineSchema } from '../schema/Line.js';\nimport { DIR_LINE } from '../constants.js';\nimport type { IStore } from '../repo/common/store.js';\nimport type { ValidationContext, ValidationError } from './types.js';\nimport { loadJson } from './utils.js';\n\nexport function validateLineSchema(data: unknown): ValidationError[] {\n const result = LineSchema.safeParse(data);\n if (result.success) return [];\n return result.error.issues.map((i) => ({\n file: '',\n message: `${i.path.length > 0 ? i.path.join('.') : 'root'}: ${i.message}`,\n }));\n}\n\nexport function validateLineRelationships(\n data: z.infer<typeof LineSchema>,\n ctx: ValidationContext,\n file: string,\n): ValidationError[] {\n const errors: ValidationError[] = [];\n\n for (const op of data.operators) {\n if (!ctx.operatorIds.has(op.operatorId)) {\n errors.push({\n file,\n message: `operators[].operatorId \"${op.operatorId}\" does not exist`,\n });\n }\n }\n\n for (const serviceId of data.serviceIds) {\n if (!ctx.serviceIds.has(serviceId)) {\n errors.push({\n file,\n message: `serviceIds: \"${serviceId}\" does not exist`,\n });\n }\n }\n\n return errors;\n}\n\nexport function validateLines(store: IStore): ValidationError[] {\n const errors: ValidationError[] = [];\n try {\n const files = store.listDir(DIR_LINE);\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n const relPath = join(DIR_LINE, file);\n const raw = loadJson<unknown>(store, relPath);\n if (raw === null) {\n errors.push({ file: relPath, message: 'Failed to parse JSON' });\n continue;\n }\n const schemaErrs = validateLineSchema(raw);\n for (const e of schemaErrs) {\n errors.push({ ...e, file: e.file || relPath });\n }\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n errors.push({\n file: DIR_LINE,\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n return errors;\n}\n\nexport function validateLinesRelationships(\n store: IStore,\n ctx?: ValidationContext,\n): ValidationError[] {\n if (!ctx) return [];\n const errors: ValidationError[] = [];\n try {\n const files = store.listDir(DIR_LINE);\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n const relPath = join(DIR_LINE, file);\n const raw = loadJson<unknown>(store, relPath);\n if (raw === null) continue;\n const parsed = LineSchema.safeParse(raw);\n if (parsed.success) {\n errors.push(...validateLineRelationships(parsed.data, ctx, relPath));\n }\n }\n } catch {\n // ignore\n }\n return errors;\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import type { IStore } from '../repo/common/store.js';
2
+ import type { ValidationError } from './types.js';
3
+ export declare function validateOperatorSchema(data: unknown): {
4
+ file: string;
5
+ message: string;
6
+ }[];
7
+ export declare function validateOperators(store: IStore): ValidationError[];
@@ -0,0 +1,43 @@
1
+ import { join } from 'node:path';
2
+ import { OperatorSchema } from '../schema/Operator.js';
3
+ import { DIR_OPERATOR } from '../constants.js';
4
+ import { loadJson } from './utils.js';
5
+ export function validateOperatorSchema(data) {
6
+ const result = OperatorSchema.safeParse(data);
7
+ if (result.success)
8
+ return [];
9
+ return result.error.issues.map((i) => ({
10
+ file: '',
11
+ message: `${i.path.length > 0 ? i.path.join('.') : 'root'}: ${i.message}`,
12
+ }));
13
+ }
14
+ export function validateOperators(store) {
15
+ const errors = [];
16
+ try {
17
+ const files = store.listDir(DIR_OPERATOR);
18
+ for (const file of files) {
19
+ if (!file.endsWith('.json'))
20
+ continue;
21
+ const relPath = join(DIR_OPERATOR, file);
22
+ const raw = loadJson(store, relPath);
23
+ if (raw === null) {
24
+ errors.push({ file: relPath, message: 'Failed to parse JSON' });
25
+ continue;
26
+ }
27
+ const schemaErrs = validateOperatorSchema(raw);
28
+ for (const e of schemaErrs) {
29
+ errors.push({ ...e, file: e.file || relPath });
30
+ }
31
+ }
32
+ }
33
+ catch (err) {
34
+ if (err.code !== 'ENOENT') {
35
+ errors.push({
36
+ file: DIR_OPERATOR,
37
+ message: err instanceof Error ? err.message : String(err),
38
+ });
39
+ }
40
+ }
41
+ return errors;
42
+ }
43
+ //# sourceMappingURL=operator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"operator.js","sourceRoot":"/","sources":["validators/operator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAG/C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,UAAU,sBAAsB,CACpC,IAAa;IAEb,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAC9B,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACrC,IAAI,EAAE,EAAE;QACR,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,EAAE;KAC1E,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;QAC1C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,SAAS;YACtC,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;YACzC,MAAM,GAAG,GAAG,QAAQ,CAAU,KAAK,EAAE,OAAO,CAAC,CAAC;YAC9C,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBACjB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC,CAAC;gBAChE,SAAS;YACX,CAAC;YACD,MAAM,UAAU,GAAG,sBAAsB,CAAC,GAAG,CAAC,CAAC;YAC/C,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;gBAC3B,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,YAAY;gBAClB,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aAC1D,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import { join } from 'node:path';\nimport { OperatorSchema } from '../schema/Operator.js';\nimport { DIR_OPERATOR } from '../constants.js';\nimport type { IStore } from '../repo/common/store.js';\nimport type { ValidationError } from './types.js';\nimport { loadJson } from './utils.js';\n\nexport function validateOperatorSchema(\n data: unknown,\n): { file: string; message: string }[] {\n const result = OperatorSchema.safeParse(data);\n if (result.success) return [];\n return result.error.issues.map((i) => ({\n file: '',\n message: `${i.path.length > 0 ? i.path.join('.') : 'root'}: ${i.message}`,\n }));\n}\n\nexport function validateOperators(store: IStore): ValidationError[] {\n const errors: ValidationError[] = [];\n try {\n const files = store.listDir(DIR_OPERATOR);\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n const relPath = join(DIR_OPERATOR, file);\n const raw = loadJson<unknown>(store, relPath);\n if (raw === null) {\n errors.push({ file: relPath, message: 'Failed to parse JSON' });\n continue;\n }\n const schemaErrs = validateOperatorSchema(raw);\n for (const e of schemaErrs) {\n errors.push({ ...e, file: e.file || relPath });\n }\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n errors.push({\n file: DIR_OPERATOR,\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n return errors;\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import type z from 'zod';
2
+ import type { IStore } from '../repo/common/store.js';
3
+ import { ServiceSchema } from '../schema/Service.js';
4
+ import type { ValidationContext, ValidationError } from './types.js';
5
+ export declare function validateServiceSchema(data: unknown): ValidationError[];
6
+ export declare function validateServiceRelationships(data: z.infer<typeof ServiceSchema>, ctx: ValidationContext, file: string): ValidationError[];
7
+ export declare function validateServices(store: IStore): ValidationError[];
8
+ export declare function validateServicesRelationships(store: IStore, ctx?: ValidationContext): ValidationError[];
@@ -0,0 +1,87 @@
1
+ import { join } from 'node:path';
2
+ import { DIR_SERVICE } from '../constants.js';
3
+ import { ServiceSchema } from '../schema/Service.js';
4
+ import { loadJson } from './utils.js';
5
+ export function validateServiceSchema(data) {
6
+ const result = ServiceSchema.safeParse(data);
7
+ if (result.success)
8
+ return [];
9
+ return result.error.issues.map((i) => ({
10
+ file: '',
11
+ message: `${i.path.length > 0 ? i.path.join('.') : 'root'}: ${i.message}`,
12
+ }));
13
+ }
14
+ export function validateServiceRelationships(data, ctx, file) {
15
+ const errors = [];
16
+ if (!ctx.lineIds.has(data.lineId)) {
17
+ errors.push({
18
+ file,
19
+ message: `lineId "${data.lineId}" does not exist`,
20
+ });
21
+ }
22
+ for (const rev of data.revisions) {
23
+ for (const st of rev.path.stations) {
24
+ if (!ctx.stationIds.has(st.stationId)) {
25
+ errors.push({
26
+ file,
27
+ message: `revisions[].path.stations[].stationId "${st.stationId}" does not exist`,
28
+ });
29
+ }
30
+ }
31
+ }
32
+ return errors;
33
+ }
34
+ export function validateServices(store) {
35
+ const errors = [];
36
+ try {
37
+ const files = store.listDir(DIR_SERVICE);
38
+ for (const file of files) {
39
+ if (!file.endsWith('.json'))
40
+ continue;
41
+ const relPath = join(DIR_SERVICE, file);
42
+ const raw = loadJson(store, relPath);
43
+ if (raw === null) {
44
+ errors.push({ file: relPath, message: 'Failed to parse JSON' });
45
+ continue;
46
+ }
47
+ const schemaErrs = validateServiceSchema(raw);
48
+ for (const e of schemaErrs) {
49
+ errors.push({ ...e, file: e.file || relPath });
50
+ }
51
+ }
52
+ }
53
+ catch (err) {
54
+ if (err.code !== 'ENOENT') {
55
+ errors.push({
56
+ file: DIR_SERVICE,
57
+ message: err instanceof Error ? err.message : String(err),
58
+ });
59
+ }
60
+ }
61
+ return errors;
62
+ }
63
+ export function validateServicesRelationships(store, ctx) {
64
+ if (!ctx)
65
+ return [];
66
+ const errors = [];
67
+ try {
68
+ const files = store.listDir(DIR_SERVICE);
69
+ for (const file of files) {
70
+ if (!file.endsWith('.json'))
71
+ continue;
72
+ const relPath = join(DIR_SERVICE, file);
73
+ const raw = loadJson(store, relPath);
74
+ if (raw === null)
75
+ continue;
76
+ const parsed = ServiceSchema.safeParse(raw);
77
+ if (parsed.success) {
78
+ errors.push(...validateServiceRelationships(parsed.data, ctx, relPath));
79
+ }
80
+ }
81
+ }
82
+ catch {
83
+ // ignore
84
+ }
85
+ return errors;
86
+ }
87
+ //# sourceMappingURL=service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"service.js","sourceRoot":"/","sources":["validators/service.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from 'node:path';\nimport type z from 'zod';\nimport { DIR_SERVICE } from '../constants.js';\nimport type { IStore } from '../repo/common/store.js';\nimport { ServiceSchema } from '../schema/Service.js';\nimport type { ValidationContext, ValidationError } from './types.js';\nimport { loadJson } from './utils.js';\n\nexport function validateServiceSchema(data: unknown): ValidationError[] {\n const result = ServiceSchema.safeParse(data);\n if (result.success) return [];\n return result.error.issues.map((i) => ({\n file: '',\n message: `${i.path.length > 0 ? i.path.join('.') : 'root'}: ${i.message}`,\n }));\n}\n\nexport function validateServiceRelationships(\n data: z.infer<typeof ServiceSchema>,\n ctx: ValidationContext,\n file: string,\n): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (!ctx.lineIds.has(data.lineId)) {\n errors.push({\n file,\n message: `lineId \"${data.lineId}\" does not exist`,\n });\n }\n\n for (const rev of data.revisions) {\n for (const st of rev.path.stations) {\n if (!ctx.stationIds.has(st.stationId)) {\n errors.push({\n file,\n message: `revisions[].path.stations[].stationId \"${st.stationId}\" does not exist`,\n });\n }\n }\n }\n\n return errors;\n}\n\nexport function validateServices(store: IStore): ValidationError[] {\n const errors: ValidationError[] = [];\n try {\n const files = store.listDir(DIR_SERVICE);\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n const relPath = join(DIR_SERVICE, file);\n const raw = loadJson<unknown>(store, relPath);\n if (raw === null) {\n errors.push({ file: relPath, message: 'Failed to parse JSON' });\n continue;\n }\n const schemaErrs = validateServiceSchema(raw);\n for (const e of schemaErrs) {\n errors.push({ ...e, file: e.file || relPath });\n }\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n errors.push({\n file: DIR_SERVICE,\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n return errors;\n}\n\nexport function validateServicesRelationships(\n store: IStore,\n ctx?: ValidationContext,\n): ValidationError[] {\n if (!ctx) return [];\n const errors: ValidationError[] = [];\n try {\n const files = store.listDir(DIR_SERVICE);\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n const relPath = join(DIR_SERVICE, file);\n const raw = loadJson<unknown>(store, relPath);\n if (raw === null) continue;\n const parsed = ServiceSchema.safeParse(raw);\n if (parsed.success) {\n errors.push(...validateServiceRelationships(parsed.data, ctx, relPath));\n }\n }\n } catch {\n // ignore\n }\n return errors;\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import type z from 'zod';
2
+ import type { IStore } from '../repo/common/store.js';
3
+ import { StationSchema } from '../schema/Station.js';
4
+ import type { ValidationContext, ValidationError } from './types.js';
5
+ export declare function validateStationSchema(data: unknown): ValidationError[];
6
+ export declare function validateStationRelationships(data: z.infer<typeof StationSchema>, ctx: ValidationContext, file: string): ValidationError[];
7
+ export declare function validateStations(store: IStore): ValidationError[];
8
+ export declare function validateStationsRelationships(store: IStore, ctx?: ValidationContext): ValidationError[];
@@ -0,0 +1,93 @@
1
+ import { join } from 'node:path';
2
+ import { DIR_STATION } from '../constants.js';
3
+ import { StationSchema } from '../schema/Station.js';
4
+ import { loadJson } from './utils.js';
5
+ export function validateStationSchema(data) {
6
+ const result = StationSchema.safeParse(data);
7
+ if (result.success)
8
+ return [];
9
+ return result.error.issues.map((i) => ({
10
+ file: '',
11
+ message: `${i.path.length > 0 ? i.path.join('.') : 'root'}: ${i.message}`,
12
+ }));
13
+ }
14
+ export function validateStationRelationships(data, ctx, file) {
15
+ const errors = [];
16
+ if (!ctx.townIds.has(data.townId)) {
17
+ errors.push({
18
+ file,
19
+ message: `townId "${data.townId}" does not exist`,
20
+ });
21
+ }
22
+ for (const landmarkId of data.landmarkIds) {
23
+ if (!ctx.landmarkIds.has(landmarkId)) {
24
+ errors.push({
25
+ file,
26
+ message: `landmarkIds: "${landmarkId}" does not exist`,
27
+ });
28
+ }
29
+ }
30
+ for (const sc of data.stationCodes) {
31
+ if (!ctx.lineIds.has(sc.lineId)) {
32
+ errors.push({
33
+ file,
34
+ message: `stationCodes[].lineId "${sc.lineId}" does not exist`,
35
+ });
36
+ }
37
+ }
38
+ return errors;
39
+ }
40
+ export function validateStations(store) {
41
+ const errors = [];
42
+ try {
43
+ const files = store.listDir(DIR_STATION);
44
+ for (const file of files) {
45
+ if (!file.endsWith('.json'))
46
+ continue;
47
+ const relPath = join(DIR_STATION, file);
48
+ const raw = loadJson(store, relPath);
49
+ if (raw === null) {
50
+ errors.push({ file: relPath, message: 'Failed to parse JSON' });
51
+ continue;
52
+ }
53
+ const schemaErrs = validateStationSchema(raw);
54
+ for (const e of schemaErrs) {
55
+ errors.push({ ...e, file: e.file || relPath });
56
+ }
57
+ }
58
+ }
59
+ catch (err) {
60
+ if (err.code !== 'ENOENT') {
61
+ errors.push({
62
+ file: DIR_STATION,
63
+ message: err instanceof Error ? err.message : String(err),
64
+ });
65
+ }
66
+ }
67
+ return errors;
68
+ }
69
+ export function validateStationsRelationships(store, ctx) {
70
+ if (!ctx)
71
+ return [];
72
+ const errors = [];
73
+ try {
74
+ const files = store.listDir(DIR_STATION);
75
+ for (const file of files) {
76
+ if (!file.endsWith('.json'))
77
+ continue;
78
+ const relPath = join(DIR_STATION, file);
79
+ const raw = loadJson(store, relPath);
80
+ if (raw === null)
81
+ continue;
82
+ const parsed = StationSchema.safeParse(raw);
83
+ if (parsed.success) {
84
+ errors.push(...validateStationRelationships(parsed.data, ctx, relPath));
85
+ }
86
+ }
87
+ }
88
+ catch {
89
+ // ignore
90
+ }
91
+ return errors;
92
+ }
93
+ //# sourceMappingURL=station.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"station.js","sourceRoot":"/","sources":["validators/station.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from 'node:path';\nimport type z from 'zod';\nimport { DIR_STATION } from '../constants.js';\nimport type { IStore } from '../repo/common/store.js';\nimport { StationSchema } from '../schema/Station.js';\nimport type { ValidationContext, ValidationError } from './types.js';\nimport { loadJson } from './utils.js';\n\nexport function validateStationSchema(data: unknown): ValidationError[] {\n const result = StationSchema.safeParse(data);\n if (result.success) return [];\n return result.error.issues.map((i) => ({\n file: '',\n message: `${i.path.length > 0 ? i.path.join('.') : 'root'}: ${i.message}`,\n }));\n}\n\nexport function validateStationRelationships(\n data: z.infer<typeof StationSchema>,\n ctx: ValidationContext,\n file: string,\n): ValidationError[] {\n const errors: ValidationError[] = [];\n\n if (!ctx.townIds.has(data.townId)) {\n errors.push({\n file,\n message: `townId \"${data.townId}\" does not exist`,\n });\n }\n\n for (const landmarkId of data.landmarkIds) {\n if (!ctx.landmarkIds.has(landmarkId)) {\n errors.push({\n file,\n message: `landmarkIds: \"${landmarkId}\" does not exist`,\n });\n }\n }\n\n for (const sc of data.stationCodes) {\n if (!ctx.lineIds.has(sc.lineId)) {\n errors.push({\n file,\n message: `stationCodes[].lineId \"${sc.lineId}\" does not exist`,\n });\n }\n }\n\n return errors;\n}\n\nexport function validateStations(store: IStore): ValidationError[] {\n const errors: ValidationError[] = [];\n try {\n const files = store.listDir(DIR_STATION);\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n const relPath = join(DIR_STATION, file);\n const raw = loadJson<unknown>(store, relPath);\n if (raw === null) {\n errors.push({ file: relPath, message: 'Failed to parse JSON' });\n continue;\n }\n const schemaErrs = validateStationSchema(raw);\n for (const e of schemaErrs) {\n errors.push({ ...e, file: e.file || relPath });\n }\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n errors.push({\n file: DIR_STATION,\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n return errors;\n}\n\nexport function validateStationsRelationships(\n store: IStore,\n ctx?: ValidationContext,\n): ValidationError[] {\n if (!ctx) return [];\n const errors: ValidationError[] = [];\n try {\n const files = store.listDir(DIR_STATION);\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n const relPath = join(DIR_STATION, file);\n const raw = loadJson<unknown>(store, relPath);\n if (raw === null) continue;\n const parsed = StationSchema.safeParse(raw);\n if (parsed.success) {\n errors.push(...validateStationRelationships(parsed.data, ctx, relPath));\n }\n }\n } catch {\n // ignore\n }\n return errors;\n}\n"]}
@@ -0,0 +1,7 @@
1
+ import type { IStore } from '../repo/common/store.js';
2
+ import type { ValidationError } from './types.js';
3
+ export declare function validateTownSchema(data: unknown): {
4
+ file: string;
5
+ message: string;
6
+ }[];
7
+ export declare function validateTowns(store: IStore): ValidationError[];
@@ -0,0 +1,43 @@
1
+ import { join } from 'node:path';
2
+ import { TownSchema } from '../schema/Town.js';
3
+ import { DIR_TOWN } from '../constants.js';
4
+ import { loadJson } from './utils.js';
5
+ export function validateTownSchema(data) {
6
+ const result = TownSchema.safeParse(data);
7
+ if (result.success)
8
+ return [];
9
+ return result.error.issues.map((i) => ({
10
+ file: '',
11
+ message: `${i.path.length > 0 ? i.path.join('.') : 'root'}: ${i.message}`,
12
+ }));
13
+ }
14
+ export function validateTowns(store) {
15
+ const errors = [];
16
+ try {
17
+ const files = store.listDir(DIR_TOWN);
18
+ for (const file of files) {
19
+ if (!file.endsWith('.json'))
20
+ continue;
21
+ const relPath = join(DIR_TOWN, file);
22
+ const raw = loadJson(store, relPath);
23
+ if (raw === null) {
24
+ errors.push({ file: relPath, message: 'Failed to parse JSON' });
25
+ continue;
26
+ }
27
+ const schemaErrs = validateTownSchema(raw);
28
+ for (const e of schemaErrs) {
29
+ errors.push({ ...e, file: e.file || relPath });
30
+ }
31
+ }
32
+ }
33
+ catch (err) {
34
+ if (err.code !== 'ENOENT') {
35
+ errors.push({
36
+ file: DIR_TOWN,
37
+ message: err instanceof Error ? err.message : String(err),
38
+ });
39
+ }
40
+ }
41
+ return errors;
42
+ }
43
+ //# sourceMappingURL=town.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"town.js","sourceRoot":"/","sources":["validators/town.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAE3C,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,UAAU,kBAAkB,CAChC,IAAa;IAEb,MAAM,MAAM,GAAG,UAAU,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC1C,IAAI,MAAM,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IAC9B,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACrC,IAAI,EAAE,EAAE;QACR,OAAO,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,EAAE;KAC1E,CAAC,CAAC,CAAC;AACN,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,MAAM,MAAM,GAAsB,EAAE,CAAC;IACrC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACtC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;gBAAE,SAAS;YACtC,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;YACrC,MAAM,GAAG,GAAG,QAAQ,CAAU,KAAK,EAAE,OAAO,CAAC,CAAC;YAC9C,IAAI,GAAG,KAAK,IAAI,EAAE,CAAC;gBACjB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,sBAAsB,EAAE,CAAC,CAAC;gBAChE,SAAS;YACX,CAAC;YACD,MAAM,UAAU,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC;YAC3C,KAAK,MAAM,CAAC,IAAI,UAAU,EAAE,CAAC;gBAC3B,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC,CAAC;YACjD,CAAC;QACH,CAAC;IACH,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAK,GAA6B,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACrD,MAAM,CAAC,IAAI,CAAC;gBACV,IAAI,EAAE,QAAQ;gBACd,OAAO,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;aAC1D,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC","sourcesContent":["import { join } from 'node:path';\nimport type { IStore } from '../repo/common/store.js';\nimport { TownSchema } from '../schema/Town.js';\nimport { DIR_TOWN } from '../constants.js';\nimport type { ValidationError } from './types.js';\nimport { loadJson } from './utils.js';\n\nexport function validateTownSchema(\n data: unknown,\n): { file: string; message: string }[] {\n const result = TownSchema.safeParse(data);\n if (result.success) return [];\n return result.error.issues.map((i) => ({\n file: '',\n message: `${i.path.length > 0 ? i.path.join('.') : 'root'}: ${i.message}`,\n }));\n}\n\nexport function validateTowns(store: IStore): ValidationError[] {\n const errors: ValidationError[] = [];\n try {\n const files = store.listDir(DIR_TOWN);\n for (const file of files) {\n if (!file.endsWith('.json')) continue;\n const relPath = join(DIR_TOWN, file);\n const raw = loadJson<unknown>(store, relPath);\n if (raw === null) {\n errors.push({ file: relPath, message: 'Failed to parse JSON' });\n continue;\n }\n const schemaErrs = validateTownSchema(raw);\n for (const e of schemaErrs) {\n errors.push({ ...e, file: e.file || relPath });\n }\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== 'ENOENT') {\n errors.push({\n file: DIR_TOWN,\n message: err instanceof Error ? err.message : String(err),\n });\n }\n }\n return errors;\n}\n"]}
@@ -0,0 +1,19 @@
1
+ export interface ValidationError {
2
+ file: string;
3
+ line?: number;
4
+ message: string;
5
+ }
6
+ /**
7
+ * Set of entity IDs loaded from data. Used for relationship validation.
8
+ * When omitted, validators run schema validation only (no relationship checks).
9
+ */
10
+ export interface ValidationContext {
11
+ townIds: Set<string>;
12
+ landmarkIds: Set<string>;
13
+ operatorIds: Set<string>;
14
+ lineIds: Set<string>;
15
+ serviceIds: Set<string>;
16
+ stationIds: Set<string>;
17
+ /** evidence IDs per issue path (e.g. "issue/2025/03/2025-03-11-x") */
18
+ evidenceIdsByIssue: Map<string, Set<string>>;
19
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"/","sources":["validators/types.ts"],"names":[],"mappings":"","sourcesContent":["export interface ValidationError {\n file: string;\n line?: number;\n message: string;\n}\n\n/**\n * Set of entity IDs loaded from data. Used for relationship validation.\n * When omitted, validators run schema validation only (no relationship checks).\n */\nexport interface ValidationContext {\n townIds: Set<string>;\n landmarkIds: Set<string>;\n operatorIds: Set<string>;\n lineIds: Set<string>;\n serviceIds: Set<string>;\n stationIds: Set<string>;\n /** evidence IDs per issue path (e.g. \"issue/2025/03/2025-03-11-x\") */\n evidenceIdsByIssue: Map<string, Set<string>>;\n}\n"]}
@@ -0,0 +1,2 @@
1
+ import type { IStore } from '../repo/common/store.js';
2
+ export declare function loadJson<T>(store: IStore, path: string): T | null;
@@ -0,0 +1,9 @@
1
+ export function loadJson(store, path) {
2
+ try {
3
+ return store.readJson(path);
4
+ }
5
+ catch {
6
+ return null;
7
+ }
8
+ }
9
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"/","sources":["validators/utils.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,QAAQ,CAAI,KAAa,EAAE,IAAY;IACrD,IAAI,CAAC;QACH,OAAO,KAAK,CAAC,QAAQ,CAAI,IAAI,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC","sourcesContent":["import type { IStore } from '../repo/common/store.js';\n\nexport function loadJson<T>(store: IStore, path: string): T | null {\n try {\n return store.readJson<T>(path);\n } catch {\n return null;\n }\n}\n"]}
@@ -1,6 +1,6 @@
1
- import type { Evidence } from '#schema/issue/evidence.js';
2
- import type { ImpactEvent } from '#schema/issue/impactEvent.js';
3
- import type { Issue } from '#schema/issue/issue.js';
1
+ import type { Evidence } from '../../schema/issue/evidence.js';
2
+ import type { ImpactEvent } from '../../schema/issue/impactEvent.js';
3
+ import type { Issue } from '../../schema/issue/issue.js';
4
4
  import type { IWriteStore } from '../common/store.js';
5
5
  export declare class IssueWriter {
6
6
  private readonly store;
@@ -1 +1 @@
1
- {"version":3,"file":"IssueWriter.js","sourceRoot":"/","sources":["write/issue/IssueWriter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAIjC,OAAO,EACL,SAAS,EACT,UAAU,EACV,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAG5B,MAAM,OAAO,WAAW;IACL,KAAK,CAAc;IAEpC,YAAY,KAAkB;QAC5B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,MAAM,CAAC,KAAY;QACjB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,KAAK,CAAC,CAAC;QACxD,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,mBAAmB,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,iBAAiB,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,cAAc,CAAC,OAAe,EAAE,QAAkB;QAChD,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;QAChD,IAAI,CAAC,KAAK,CAAC,UAAU,CACnB,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,mBAAmB,CAAC,EACpD,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CACpC,CAAC;IACJ,CAAC;IAED,YAAY,CAAC,OAAe,EAAE,MAAmB;QAC/C,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;QAChD,IAAI,CAAC,KAAK,CAAC,UAAU,CACnB,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC,EAClD,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAClC,CAAC;IACJ,CAAC;IAEO,WAAW,CAAC,OAAe;QACjC,MAAM,OAAO,GAAG,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC;QACjC,OAAO,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;CACF","sourcesContent":["import { join } from 'node:path';\nimport { NdJson } from 'json-nd';\nimport type { Evidence } from '#schema/issue/evidence.js';\nimport type { ImpactEvent } from '#schema/issue/impactEvent.js';\nimport type { Issue } from '#schema/issue/issue.js';\nimport {\n DIR_ISSUE,\n FILE_ISSUE,\n FILE_ISSUE_EVIDENCE,\n FILE_ISSUE_IMPACT,\n} from '../../constants.js';\nimport type { IWriteStore } from '../common/store.js';\n\nexport class IssueWriter {\n private readonly store: IWriteStore;\n\n constructor(store: IWriteStore) {\n this.store = store;\n }\n\n create(issue: Issue): void {\n const issueDir = this.getIssueDir(issue.id);\n this.store.ensureDir(issueDir);\n this.store.writeJson(join(issueDir, FILE_ISSUE), issue);\n this.store.writeText(join(issueDir, FILE_ISSUE_EVIDENCE), '');\n this.store.writeText(join(issueDir, FILE_ISSUE_IMPACT), '');\n }\n\n appendEvidence(issueId: string, evidence: Evidence): void {\n this.store.ensureDir(this.getIssueDir(issueId));\n this.store.appendText(\n join(this.getIssueDir(issueId), FILE_ISSUE_EVIDENCE),\n `${NdJson.stringify([evidence])}\\n`,\n );\n }\n\n appendImpact(issueId: string, impact: ImpactEvent): void {\n this.store.ensureDir(this.getIssueDir(issueId));\n this.store.appendText(\n join(this.getIssueDir(issueId), FILE_ISSUE_IMPACT),\n `${NdJson.stringify([impact])}\\n`,\n );\n }\n\n private getIssueDir(issueId: string): string {\n const tsMatch = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(issueId);\n if (!tsMatch) {\n throw new Error(`Invalid issue ID: ${issueId}`);\n }\n const [_, year, month] = tsMatch;\n return join(DIR_ISSUE, year, month, issueId);\n }\n}\n"]}
1
+ {"version":3,"file":"IssueWriter.js","sourceRoot":"/","sources":["write/issue/IssueWriter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAIjC,OAAO,EACL,SAAS,EACT,UAAU,EACV,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AAG5B,MAAM,OAAO,WAAW;IACL,KAAK,CAAc;IAEpC,YAAY,KAAkB;QAC5B,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;IAED,MAAM,CAAC,KAAY;QACjB,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAC5C,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,UAAU,CAAC,EAAE,KAAK,CAAC,CAAC;QACxD,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,mBAAmB,CAAC,EAAE,EAAE,CAAC,CAAC;QAC9D,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,QAAQ,EAAE,iBAAiB,CAAC,EAAE,EAAE,CAAC,CAAC;IAC9D,CAAC;IAED,cAAc,CAAC,OAAe,EAAE,QAAkB;QAChD,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;QAChD,IAAI,CAAC,KAAK,CAAC,UAAU,CACnB,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,mBAAmB,CAAC,EACpD,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,IAAI,CACpC,CAAC;IACJ,CAAC;IAED,YAAY,CAAC,OAAe,EAAE,MAAmB;QAC/C,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC;QAChD,IAAI,CAAC,KAAK,CAAC,UAAU,CACnB,IAAI,CAAC,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,EAAE,iBAAiB,CAAC,EAClD,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAClC,CAAC;IACJ,CAAC;IAEO,WAAW,CAAC,OAAe;QACjC,MAAM,OAAO,GAAG,0BAA0B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACzD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,MAAM,IAAI,KAAK,CAAC,qBAAqB,OAAO,EAAE,CAAC,CAAC;QAClD,CAAC;QACD,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC;QACjC,OAAO,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;CACF","sourcesContent":["import { join } from 'node:path';\nimport { NdJson } from 'json-nd';\nimport type { Evidence } from '../../schema/issue/evidence.js';\nimport type { ImpactEvent } from '../../schema/issue/impactEvent.js';\nimport type { Issue } from '../../schema/issue/issue.js';\nimport {\n DIR_ISSUE,\n FILE_ISSUE,\n FILE_ISSUE_EVIDENCE,\n FILE_ISSUE_IMPACT,\n} from '../../constants.js';\nimport type { IWriteStore } from '../common/store.js';\n\nexport class IssueWriter {\n private readonly store: IWriteStore;\n\n constructor(store: IWriteStore) {\n this.store = store;\n }\n\n create(issue: Issue): void {\n const issueDir = this.getIssueDir(issue.id);\n this.store.ensureDir(issueDir);\n this.store.writeJson(join(issueDir, FILE_ISSUE), issue);\n this.store.writeText(join(issueDir, FILE_ISSUE_EVIDENCE), '');\n this.store.writeText(join(issueDir, FILE_ISSUE_IMPACT), '');\n }\n\n appendEvidence(issueId: string, evidence: Evidence): void {\n this.store.ensureDir(this.getIssueDir(issueId));\n this.store.appendText(\n join(this.getIssueDir(issueId), FILE_ISSUE_EVIDENCE),\n `${NdJson.stringify([evidence])}\\n`,\n );\n }\n\n appendImpact(issueId: string, impact: ImpactEvent): void {\n this.store.ensureDir(this.getIssueDir(issueId));\n this.store.appendText(\n join(this.getIssueDir(issueId), FILE_ISSUE_IMPACT),\n `${NdJson.stringify([impact])}\\n`,\n );\n }\n\n private getIssueDir(issueId: string): string {\n const tsMatch = /^(\\d{4})-(\\d{2})-(\\d{2})/.exec(issueId);\n if (!tsMatch) {\n throw new Error(`Invalid issue ID: ${issueId}`);\n }\n const [_, year, month] = tsMatch;\n return join(DIR_ISSUE, year, month, issueId);\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mrtdown/core",
3
- "version": "2.0.0-alpha.3",
3
+ "version": "2.0.0-alpha.5",
4
4
  "description": "Data repository",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -29,12 +29,7 @@
29
29
  "vitest-evals": "^0.5.0"
30
30
  },
31
31
  "files": [
32
- "dist",
33
- "!dist/cli",
34
- "!dist/legacy",
35
- "!dist/llm",
36
- "!dist/scripts",
37
- "!dist/validators"
32
+ "dist"
38
33
  ],
39
34
  "exports": {
40
35
  ".": {