@cyanheads/eurostat-mcp-server 0.11.1 → 0.11.3

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 (104) hide show
  1. package/AGENTS.md +6 -4
  2. package/CLAUDE.md +6 -4
  3. package/README.md +20 -17
  4. package/changelog/0.11.x/0.11.2.md +27 -0
  5. package/changelog/0.11.x/0.11.3.md +45 -0
  6. package/changelog/template.md +10 -3
  7. package/dist/config/server-config.js +1 -1
  8. package/dist/config/server-config.js.map +1 -1
  9. package/dist/mcp-server/resources/definitions/eurostat-dataset.resource.d.ts +14 -1
  10. package/dist/mcp-server/resources/definitions/eurostat-dataset.resource.d.ts.map +1 -1
  11. package/dist/mcp-server/resources/definitions/eurostat-dataset.resource.js +17 -0
  12. package/dist/mcp-server/resources/definitions/eurostat-dataset.resource.js.map +1 -1
  13. package/dist/mcp-server/tools/definitions/eurostat-browse-themes.tool.d.ts +1 -1
  14. package/dist/mcp-server/tools/definitions/eurostat-browse-themes.tool.js +2 -2
  15. package/dist/mcp-server/tools/definitions/eurostat-browse-themes.tool.js.map +1 -1
  16. package/dist/mcp-server/tools/definitions/eurostat-dataframe-describe.tool.js +2 -2
  17. package/dist/mcp-server/tools/definitions/eurostat-dataframe-describe.tool.js.map +1 -1
  18. package/dist/mcp-server/tools/definitions/eurostat-dataframe-drop.tool.js +1 -1
  19. package/dist/mcp-server/tools/definitions/eurostat-dataframe-drop.tool.js.map +1 -1
  20. package/dist/mcp-server/tools/definitions/eurostat-dataframe-query.tool.js +1 -1
  21. package/dist/mcp-server/tools/definitions/eurostat-dataframe-query.tool.js.map +1 -1
  22. package/dist/mcp-server/tools/definitions/eurostat-download-dataset.tool.d.ts +26 -12
  23. package/dist/mcp-server/tools/definitions/eurostat-download-dataset.tool.d.ts.map +1 -1
  24. package/dist/mcp-server/tools/definitions/eurostat-download-dataset.tool.js +181 -47
  25. package/dist/mcp-server/tools/definitions/eurostat-download-dataset.tool.js.map +1 -1
  26. package/dist/mcp-server/tools/definitions/eurostat-get-dataset-info.tool.d.ts +1 -1
  27. package/dist/mcp-server/tools/definitions/eurostat-get-dataset-info.tool.d.ts.map +1 -1
  28. package/dist/mcp-server/tools/definitions/eurostat-get-dataset-info.tool.js +11 -2
  29. package/dist/mcp-server/tools/definitions/eurostat-get-dataset-info.tool.js.map +1 -1
  30. package/dist/mcp-server/tools/definitions/eurostat-get-dimension-values.tool.d.ts +8 -6
  31. package/dist/mcp-server/tools/definitions/eurostat-get-dimension-values.tool.d.ts.map +1 -1
  32. package/dist/mcp-server/tools/definitions/eurostat-get-dimension-values.tool.js +149 -54
  33. package/dist/mcp-server/tools/definitions/eurostat-get-dimension-values.tool.js.map +1 -1
  34. package/dist/mcp-server/tools/definitions/eurostat-query-dataset.tool.d.ts +22 -8
  35. package/dist/mcp-server/tools/definitions/eurostat-query-dataset.tool.d.ts.map +1 -1
  36. package/dist/mcp-server/tools/definitions/eurostat-query-dataset.tool.js +215 -43
  37. package/dist/mcp-server/tools/definitions/eurostat-query-dataset.tool.js.map +1 -1
  38. package/dist/mcp-server/tools/definitions/eurostat-search-datasets.tool.d.ts +16 -6
  39. package/dist/mcp-server/tools/definitions/eurostat-search-datasets.tool.d.ts.map +1 -1
  40. package/dist/mcp-server/tools/definitions/eurostat-search-datasets.tool.js +67 -16
  41. package/dist/mcp-server/tools/definitions/eurostat-search-datasets.tool.js.map +1 -1
  42. package/dist/mcp-server/tools/narrowing-advice.d.ts +64 -3
  43. package/dist/mcp-server/tools/narrowing-advice.d.ts.map +1 -1
  44. package/dist/mcp-server/tools/narrowing-advice.js +160 -4
  45. package/dist/mcp-server/tools/narrowing-advice.js.map +1 -1
  46. package/dist/mcp-server/tools/notice-text.d.ts +18 -0
  47. package/dist/mcp-server/tools/notice-text.d.ts.map +1 -0
  48. package/dist/mcp-server/tools/notice-text.js +40 -0
  49. package/dist/mcp-server/tools/notice-text.js.map +1 -0
  50. package/dist/mcp-server/tools/value-list-paging.d.ts +11 -1
  51. package/dist/mcp-server/tools/value-list-paging.d.ts.map +1 -1
  52. package/dist/mcp-server/tools/value-list-paging.js +13 -1
  53. package/dist/mcp-server/tools/value-list-paging.js.map +1 -1
  54. package/dist/services/eurostat-bulk/eurostat-bulk-service.d.ts +7 -5
  55. package/dist/services/eurostat-bulk/eurostat-bulk-service.d.ts.map +1 -1
  56. package/dist/services/eurostat-bulk/eurostat-bulk-service.js +145 -40
  57. package/dist/services/eurostat-bulk/eurostat-bulk-service.js.map +1 -1
  58. package/dist/services/eurostat-bulk/types.d.ts +44 -4
  59. package/dist/services/eurostat-bulk/types.d.ts.map +1 -1
  60. package/dist/services/eurostat-bulk/types.js.map +1 -1
  61. package/dist/services/eurostat-catalogue/dimension-value-index.d.ts +81 -0
  62. package/dist/services/eurostat-catalogue/dimension-value-index.d.ts.map +1 -0
  63. package/dist/services/eurostat-catalogue/dimension-value-index.js +410 -0
  64. package/dist/services/eurostat-catalogue/dimension-value-index.js.map +1 -0
  65. package/dist/services/eurostat-catalogue/eurostat-catalogue-service.d.ts +100 -14
  66. package/dist/services/eurostat-catalogue/eurostat-catalogue-service.d.ts.map +1 -1
  67. package/dist/services/eurostat-catalogue/eurostat-catalogue-service.js +359 -90
  68. package/dist/services/eurostat-catalogue/eurostat-catalogue-service.js.map +1 -1
  69. package/dist/services/eurostat-catalogue/search-text.d.ts +12 -0
  70. package/dist/services/eurostat-catalogue/search-text.d.ts.map +1 -0
  71. package/dist/services/eurostat-catalogue/search-text.js +31 -0
  72. package/dist/services/eurostat-catalogue/search-text.js.map +1 -0
  73. package/dist/services/eurostat-catalogue/types.d.ts +11 -0
  74. package/dist/services/eurostat-catalogue/types.d.ts.map +1 -1
  75. package/dist/services/eurostat-codelists.d.ts +2 -1
  76. package/dist/services/eurostat-codelists.d.ts.map +1 -1
  77. package/dist/services/eurostat-codelists.js +2 -1
  78. package/dist/services/eurostat-codelists.js.map +1 -1
  79. package/dist/services/eurostat-data/eurostat-data-service.d.ts +30 -2
  80. package/dist/services/eurostat-data/eurostat-data-service.d.ts.map +1 -1
  81. package/dist/services/eurostat-data/eurostat-data-service.js +209 -19
  82. package/dist/services/eurostat-data/eurostat-data-service.js.map +1 -1
  83. package/dist/services/eurostat-data/sdmx-metadata.d.ts.map +1 -1
  84. package/dist/services/eurostat-data/sdmx-metadata.js +4 -20
  85. package/dist/services/eurostat-data/sdmx-metadata.js.map +1 -1
  86. package/dist/services/eurostat-data/types.d.ts +108 -4
  87. package/dist/services/eurostat-data/types.d.ts.map +1 -1
  88. package/dist/services/eurostat-data/types.js.map +1 -1
  89. package/dist/services/eurostat-filters.d.ts +18 -6
  90. package/dist/services/eurostat-filters.d.ts.map +1 -1
  91. package/dist/services/eurostat-filters.js +24 -7
  92. package/dist/services/eurostat-filters.js.map +1 -1
  93. package/dist/services/eurostat-periods.d.ts +54 -1
  94. package/dist/services/eurostat-periods.d.ts.map +1 -1
  95. package/dist/services/eurostat-periods.js +101 -1
  96. package/dist/services/eurostat-periods.js.map +1 -1
  97. package/dist/services/xml-entities.d.ts +13 -0
  98. package/dist/services/xml-entities.d.ts.map +1 -0
  99. package/dist/services/xml-entities.js +31 -0
  100. package/dist/services/xml-entities.js.map +1 -0
  101. package/package.json +7 -7
  102. package/server.json +5 -5
  103. package/skills/eurostat-guide/SKILL.md +6 -5
  104. package/skills/eurostat-guide/references/sql-analysis.md +21 -5
@@ -0,0 +1,410 @@
1
+ /**
2
+ * @fileoverview The dimension value index search reads when a dataset's own text lacks a
3
+ * query word: the codes Eurostat's metabase lists for each dataset (`time` excluded), each
4
+ * labelled in English from the global codelists. Both downloads are gzip files read as
5
+ * streams, never held whole; the index keeps joined strings and typed arrays.
6
+ * @module services/eurostat-catalogue/dimension-value-index
7
+ */
8
+ import { fetchWithTimeout } from '@cyanheads/mcp-ts-core/utils';
9
+ import { getServerConfig } from '../../config/server-config.js';
10
+ import { decodeXmlEntities } from '../xml-entities.js';
11
+ import { continuesWord, foldSearchText } from './search-text.js';
12
+ /** The period dimension, listed for every dataset; its codes are dates, not vocabulary. */
13
+ const TIME_DIMENSION = 'time';
14
+ /** Joins labels and codes. A search word holds no whitespace, so no match spans two labels. */
15
+ const SEPARATOR = '\n';
16
+ /**
17
+ * A codelist's opening tag, a code's opening tag, an English name, and a code's closing tag.
18
+ * `<s:Code\b` does not match `<s:Codelist`.
19
+ */
20
+ const CODELIST_TOKEN = /<s:Codelist\b[^>]*?\sid="([^"]*)"|<s:Code\b[^>]*?\sid="([^"]*)"|<c:Name xml:lang="en">([^<]*)<\/c:Name>|<\/s:Code>/g;
21
+ const CODE_CLOSE = '</s:Code>';
22
+ /** The codelist dump's root element closes the document; a stream without it was cut short. */
23
+ const DOCUMENT_CLOSE = '</m:Structure>';
24
+ /**
25
+ * A copy of `text` in a new string. A string cut from a decoded chunk keeps the whole chunk
26
+ * alive, and on JavaScriptCore so does a concatenate-then-slice copy, which slices the
27
+ * original again; a join writes new characters on every runtime.
28
+ */
29
+ function copyOf(text) {
30
+ return [text, ''].join(SEPARATOR).slice(0, -SEPARATOR.length);
31
+ }
32
+ /** Offsets of each part joined by {@link SEPARATOR}, plus one past the end. */
33
+ function offsetsOf(parts) {
34
+ const starts = new Int32Array(parts.length + 1);
35
+ for (let i = 0; i < parts.length; i++) {
36
+ starts[i + 1] = starts[i] + parts[i].length + SEPARATOR.length;
37
+ }
38
+ return starts;
39
+ }
40
+ /** The labels of the codes Eurostat's metabase lists per dataset, searchable at word starts. */
41
+ export class DimensionValueIndex {
42
+ /** Epoch ms when this index finished loading: its age, and the snapshot a cursor binds. */
43
+ loadedAt;
44
+ parts;
45
+ constructor(parts, loadedAt) {
46
+ this.parts = parts;
47
+ this.loadedAt = loadedAt;
48
+ }
49
+ /** Dataset, value, and label counts, for logging. */
50
+ get size() {
51
+ return {
52
+ datasets: this.parts.datasetIds.size,
53
+ labels: this.parts.labelStart.length - 1,
54
+ values: this.parts.valueLabel.length,
55
+ };
56
+ }
57
+ /** The id of a dataset the metabase lists, or undefined for one it does not. */
58
+ datasetOf(code) {
59
+ return this.parts.datasetIds.get(code);
60
+ }
61
+ /**
62
+ * Flags, per label id, whether `word` occurs in the folded label with no letter or digit
63
+ * right before it; undefined when no label carries it. One scan of the joined labels;
64
+ * past a label's first match the scan resumes at the next label.
65
+ */
66
+ labelsAtWordStart(word) {
67
+ const { searchStart, searchText } = this.parts;
68
+ let flags;
69
+ let at = searchText.indexOf(word);
70
+ while (at !== -1) {
71
+ if (continuesWord(searchText, at)) {
72
+ at = searchText.indexOf(word, at + 1);
73
+ continue;
74
+ }
75
+ const label = this.labelAt(at);
76
+ flags ??= new Uint8Array(searchStart.length - 1);
77
+ flags[label] = 1;
78
+ at = searchText.indexOf(word, searchStart[label + 1]);
79
+ }
80
+ return flags;
81
+ }
82
+ /** Whether some value of `dataset` has a label `flags` marks. */
83
+ hasValue(dataset, flags) {
84
+ return this.someValue(dataset, (label) => flags[label] === 1);
85
+ }
86
+ /** Whether one value of `dataset` has a label every one of `flagSets` marks. */
87
+ hasValueMarkedByAll(dataset, flagSets) {
88
+ return this.someValue(dataset, (label) => flagSets.every((flags) => flags[label] === 1));
89
+ }
90
+ /**
91
+ * The values of `dataset` whose label any of `flagSets` marks: those marked by the most
92
+ * flag sets first, so a value carrying every word leads the ones carrying one of them,
93
+ * then metabase order.
94
+ */
95
+ valuesMarked(dataset, flagSets) {
96
+ const { codeStart, codeText, datasetStart, datasetValues, dimensions, labelStart, labelText } = this.parts;
97
+ const values = [];
98
+ for (let at = datasetStart[dataset]; at < datasetStart[dataset + 1]; at++) {
99
+ const value = datasetValues[at];
100
+ const label = this.parts.valueLabel[value];
101
+ const marked = label < 0 ? 0 : flagSets.filter((flags) => flags[label] === 1).length;
102
+ if (marked === 0)
103
+ continue;
104
+ values.push({
105
+ marked,
106
+ value: {
107
+ dimension: dimensions[this.parts.valueDimension[value]],
108
+ code: codeText.slice(codeStart[value], codeStart[value + 1] - 1),
109
+ label: labelText.slice(labelStart[label], labelStart[label + 1] - 1),
110
+ },
111
+ });
112
+ }
113
+ return values.sort((a, b) => b.marked - a.marked).map(({ value }) => value);
114
+ }
115
+ someValue(dataset, test) {
116
+ const { datasetStart, datasetValues, valueLabel } = this.parts;
117
+ for (let at = datasetStart[dataset]; at < datasetStart[dataset + 1]; at++) {
118
+ const label = valueLabel[datasetValues[at]];
119
+ if (label >= 0 && test(label))
120
+ return true;
121
+ }
122
+ return false;
123
+ }
124
+ /** The label whose span of the joined search text holds offset `at`. */
125
+ labelAt(at) {
126
+ const { searchStart } = this.parts;
127
+ let low = 0;
128
+ let high = searchStart.length - 2;
129
+ while (low < high) {
130
+ const mid = (low + high + 1) >> 1;
131
+ if (searchStart[mid] <= at)
132
+ low = mid;
133
+ else
134
+ high = mid - 1;
135
+ }
136
+ return low;
137
+ }
138
+ }
139
+ /**
140
+ * Text of a stream in pieces that each end at a boundary, so no token spans two pieces. Only
141
+ * the newest chunk is searched for a boundary, so a long run without one costs its length.
142
+ */
143
+ class BoundaryPieces {
144
+ pending = [];
145
+ boundary;
146
+ constructor(boundary) {
147
+ this.boundary = boundary;
148
+ }
149
+ /** The text up to the last boundary in `chunk`, or undefined while `chunk` holds none. */
150
+ cut(chunk) {
151
+ const at = chunk.lastIndexOf(this.boundary);
152
+ if (at === -1) {
153
+ this.pending.push(chunk);
154
+ return;
155
+ }
156
+ const end = at + this.boundary.length;
157
+ this.pending.push(chunk.slice(0, end));
158
+ const piece = this.pending.join('');
159
+ this.pending = [chunk.slice(end)];
160
+ return piece;
161
+ }
162
+ /** The text after the last boundary. */
163
+ rest() {
164
+ const rest = this.pending.join('');
165
+ this.pending = [];
166
+ return rest;
167
+ }
168
+ }
169
+ /**
170
+ * Reads `dataset<TAB>dimension<TAB>code` lines as they stream in, `time` rows skipped. Every
171
+ * string it keeps is a copy, so no decoded chunk outlives its turn.
172
+ */
173
+ class MetabaseReader {
174
+ line = 0;
175
+ lines = new BoundaryPieces('\n');
176
+ table = {
177
+ datasetIds: new Map(),
178
+ dimensionIds: new Map(),
179
+ dimensions: [],
180
+ rowDatasets: [],
181
+ rowValues: [],
182
+ valueCodes: [],
183
+ valueDimensions: [],
184
+ valueIds: new Map(),
185
+ };
186
+ read(chunk) {
187
+ const text = this.lines.cut(chunk);
188
+ if (text !== undefined)
189
+ for (const line of text.slice(0, -1).split('\n'))
190
+ this.add(line);
191
+ }
192
+ /** The table read. Throws when the metabase listed no dataset: a broken download, not an empty catalogue. */
193
+ finish() {
194
+ const rest = this.lines.rest();
195
+ if (rest)
196
+ this.add(rest);
197
+ if (this.table.datasetIds.size === 0)
198
+ throw new Error('The metabase listed no dataset dimension values');
199
+ return this.table;
200
+ }
201
+ add(text) {
202
+ this.line += 1;
203
+ const line = text.endsWith('\r') ? text.slice(0, -1) : text;
204
+ if (!line)
205
+ return;
206
+ const fields = line.split('\t');
207
+ const [dataset, dimension, code] = fields;
208
+ if (fields.length !== 3 || !dataset || !dimension || code === undefined) {
209
+ throw new Error(`Metabase line ${this.line} is not a dataset, dimension and code separated by tabs`);
210
+ }
211
+ if (dimension === TIME_DIMENSION)
212
+ return;
213
+ const table = this.table;
214
+ let datasetId = table.datasetIds.get(dataset);
215
+ if (datasetId === undefined) {
216
+ datasetId = table.datasetIds.size;
217
+ table.datasetIds.set(copyOf(dataset), datasetId);
218
+ }
219
+ let dimensionId = table.dimensionIds.get(dimension);
220
+ if (dimensionId === undefined) {
221
+ dimensionId = table.dimensions.length;
222
+ table.dimensions.push(copyOf(dimension));
223
+ table.dimensionIds.set(table.dimensions[dimensionId], dimensionId);
224
+ }
225
+ const key = `${dimensionId}\t${code}`;
226
+ let valueId = table.valueIds.get(key);
227
+ if (valueId === undefined) {
228
+ valueId = table.valueCodes.length;
229
+ table.valueIds.set(copyOf(key), valueId);
230
+ table.valueCodes.push(copyOf(code));
231
+ table.valueDimensions.push(dimensionId);
232
+ }
233
+ table.rowDatasets.push(datasetId);
234
+ table.rowValues.push(valueId);
235
+ }
236
+ }
237
+ /**
238
+ * Reads the codelist dump as it streams in, keeping the first English name of each code the
239
+ * metabase lists, from the codelist named after its dimension in upper case.
240
+ */
241
+ class CodelistReader {
242
+ code;
243
+ codelistDimensions;
244
+ dimensionId;
245
+ labelled = 0;
246
+ labels;
247
+ /** Whether the open code, or the codelist before its first code, has had its name. */
248
+ named = true;
249
+ pieces = new BoundaryPieces(CODE_CLOSE);
250
+ table;
251
+ constructor(table) {
252
+ this.table = table;
253
+ this.labels = new Array(table.valueCodes.length);
254
+ this.codelistDimensions = new Map(table.dimensions.map((dimension, id) => [dimension.toUpperCase(), id]));
255
+ }
256
+ read(chunk) {
257
+ const piece = this.pieces.cut(chunk);
258
+ if (piece !== undefined)
259
+ this.scan(piece);
260
+ }
261
+ /**
262
+ * The index, from the metabase table and the labels read. Throws when the dump stops before
263
+ * its root element closes, or labels none of the metabase's codes.
264
+ */
265
+ finish() {
266
+ const rest = this.pieces.rest();
267
+ this.scan(rest);
268
+ if (!rest.includes(DOCUMENT_CLOSE)) {
269
+ throw new Error('The codelist dump ended before its root element closed');
270
+ }
271
+ if (this.labelled === 0)
272
+ throw new Error('The codelists labelled none of the metabase codes');
273
+ return assembleIndex(this.table, this.labels);
274
+ }
275
+ scan(piece) {
276
+ CODELIST_TOKEN.lastIndex = 0;
277
+ for (let token = CODELIST_TOKEN.exec(piece); token; token = CODELIST_TOKEN.exec(piece)) {
278
+ const [, codelistId, codeId, name] = token;
279
+ if (codelistId !== undefined) {
280
+ this.dimensionId = this.codelistDimensions.get(decodeXmlEntities(codelistId));
281
+ this.named = true;
282
+ }
283
+ else if (codeId !== undefined) {
284
+ this.code = decodeXmlEntities(codeId);
285
+ this.named = false;
286
+ }
287
+ else if (name !== undefined) {
288
+ // The codelist's own name precedes its first code; only a code's first name labels it.
289
+ if (this.named || this.dimensionId === undefined)
290
+ continue;
291
+ this.named = true;
292
+ const valueId = this.table.valueIds.get(`${this.dimensionId}\t${this.code}`);
293
+ if (valueId === undefined || this.labels[valueId] !== undefined)
294
+ continue;
295
+ this.labels[valueId] = copyOf(decodeXmlEntities(name).trim());
296
+ this.labelled += 1;
297
+ }
298
+ else {
299
+ this.named = true;
300
+ }
301
+ }
302
+ }
303
+ }
304
+ /** The index from the metabase table and each value's label. */
305
+ function assembleIndex(table, valueLabels) {
306
+ const { datasetIds, dimensions, rowDatasets, rowValues, valueCodes, valueDimensions } = table;
307
+ const labelIds = new Map();
308
+ const labels = [];
309
+ const valueLabel = new Int32Array(valueCodes.length).fill(-1);
310
+ valueLabels.forEach((label, valueId) => {
311
+ if (label === undefined)
312
+ return;
313
+ let labelId = labelIds.get(label);
314
+ if (labelId === undefined) {
315
+ labelId = labels.length;
316
+ labels.push(label);
317
+ labelIds.set(label, labelId);
318
+ }
319
+ valueLabel[valueId] = labelId;
320
+ });
321
+ const folded = labels.map(foldSearchText);
322
+ const datasetStart = new Int32Array(datasetIds.size + 1);
323
+ for (const datasetId of rowDatasets)
324
+ datasetStart[datasetId + 1] = datasetStart[datasetId + 1] + 1;
325
+ for (let d = 0; d < datasetIds.size; d++) {
326
+ datasetStart[d + 1] = datasetStart[d + 1] + datasetStart[d];
327
+ }
328
+ const fill = datasetStart.slice(0, -1);
329
+ const datasetValues = new Int32Array(rowValues.length);
330
+ rowDatasets.forEach((datasetId, row) => {
331
+ datasetValues[fill[datasetId]++] = rowValues[row];
332
+ });
333
+ return new DimensionValueIndex({
334
+ codeStart: offsetsOf(valueCodes),
335
+ codeText: valueCodes.join(SEPARATOR),
336
+ datasetIds,
337
+ datasetStart,
338
+ datasetValues,
339
+ dimensions,
340
+ labelStart: offsetsOf(labels),
341
+ labelText: labels.join(SEPARATOR),
342
+ searchStart: offsetsOf(folded),
343
+ searchText: folded.join(SEPARATOR),
344
+ valueDimension: Int32Array.from(valueDimensions),
345
+ valueLabel,
346
+ }, Date.now());
347
+ }
348
+ /**
349
+ * Build the index from the metabase (`dataset<TAB>dimension<TAB>code` lines) and the codelist
350
+ * dump (SDMX 2.1 structure XML), each read as a stream of decoded text. The metabase is read
351
+ * first, so only the labels of codes it lists are kept from the codelist named, in upper case,
352
+ * after each dimension. A code's first English name is its label.
353
+ *
354
+ * Throws on a metabase line that is not three tab-separated fields, a metabase that lists no
355
+ * dataset, a codelist dump that stops before its root element closes, or codelists that label
356
+ * none of the metabase's codes: each is a broken download, not an empty catalogue.
357
+ */
358
+ export async function buildDimensionValueIndex(metabase, codelists) {
359
+ const metabaseReader = new MetabaseReader();
360
+ for await (const chunk of metabase)
361
+ metabaseReader.read(chunk);
362
+ const codelistReader = new CodelistReader(metabaseReader.finish());
363
+ for await (const chunk of codelists)
364
+ codelistReader.read(chunk);
365
+ return codelistReader.finish();
366
+ }
367
+ /**
368
+ * The decoded text of a gzip file at `url`, chunk by chunk. The request starts when the
369
+ * first chunk is asked for; `timeoutMs` bounds the whole transfer.
370
+ */
371
+ async function* gzipText(url, timeoutMs, context) {
372
+ const response = await fetchWithTimeout(url, timeoutMs, context);
373
+ if (!response.body)
374
+ throw new Error(`${new URL(url).pathname} answered with no body`);
375
+ /**
376
+ * `DecompressionStream`'s writable side is typed `BufferSource`, wider than the
377
+ * `Uint8Array` chunks the body carries, so the transform is narrowed to the types in play.
378
+ */
379
+ const reader = response.body
380
+ .pipeThrough(new DecompressionStream('gzip'))
381
+ .getReader();
382
+ const decoder = new TextDecoder('utf-8');
383
+ try {
384
+ while (true) {
385
+ const { done, value } = await reader.read();
386
+ if (done)
387
+ break;
388
+ const text = decoder.decode(value, { stream: true });
389
+ if (text)
390
+ yield text;
391
+ }
392
+ const tail = decoder.decode();
393
+ if (tail)
394
+ yield tail;
395
+ }
396
+ finally {
397
+ // Ends the transfer when parsing stops early; a no-op once the stream is done.
398
+ await reader.cancel().catch(() => undefined);
399
+ reader.releaseLock();
400
+ }
401
+ }
402
+ /**
403
+ * Download and build the index: the metabase first, then the codelist dump, each within
404
+ * `EUROSTAT_BULK_TIMEOUT_MS`. One attempt; the caller schedules retries.
405
+ */
406
+ export function fetchDimensionValueIndex(context) {
407
+ const { baseUrl, bulkTimeoutMs } = getServerConfig();
408
+ return buildDimensionValueIndex(gzipText(`${baseUrl}/catalogue/metabase.txt.gz`, bulkTimeoutMs, context), gzipText(`${baseUrl}/sdmx/2.1/codelist/ESTAT/all/latest?compressed=true`, bulkTimeoutMs, context));
409
+ }
410
+ //# sourceMappingURL=dimension-value-index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dimension-value-index.js","sourceRoot":"","sources":["../../../src/services/eurostat-catalogue/dimension-value-index.ts"],"names":[],"mappings":"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"}
@@ -7,6 +7,27 @@ import type { Context } from '@cyanheads/mcp-ts-core';
7
7
  import type { AppConfig } from '@cyanheads/mcp-ts-core/config';
8
8
  import type { StorageService } from '@cyanheads/mcp-ts-core/storage';
9
9
  import type { BrowseItem, DatasetResult } from './types.js';
10
+ /** Most distinct words a search that matches no catalogue text looks for in dimension values. */
11
+ export declare const MAX_VALUE_SEARCH_WORDS = 10;
12
+ /** Most distinct words, in query order, a search that matches nothing names as held by no dataset. */
13
+ export declare const MAX_UNMATCHED_WORD_CHECKS = 32;
14
+ /**
15
+ * How a dataset matched a search, best first: 0, its label holds the words as a phrase
16
+ * starting at a word start; 1, its label or code holds every word; 2, some word matched
17
+ * only in its theme breadcrumb.
18
+ */
19
+ export type SearchTier = 0 | 1 | 2;
20
+ /**
21
+ * The tier test for one search over `words`, whitespace-free tokens as `search()` splits a
22
+ * query. The returned function ranks a dataset from its label, folded by
23
+ * {@link foldSearchText}, and its code, never its breadcrumb, so every TOC placement of a
24
+ * code ranks alike. The phrase is the words joined by single spaces and folded the same way;
25
+ * it must start where no letter or digit precedes it, so "employment rate" is not found
26
+ * inside "Unemployment rate". The word test is the substring test matching applies.
27
+ */
28
+ export declare function searchTierOf(words: readonly string[]): (foldedLabel: string, code: string) => SearchTier;
29
+ /** Why a search that matched no catalogue text did not read dimension values. */
30
+ export type ValuesNotSearched = 'index_unavailable' | 'too_many_words';
10
31
  export declare class EurostatCatalogueService {
11
32
  private cache;
12
33
  /** Shared in-flight refresh so concurrent callers past the TTL trigger one fetch. */
@@ -19,6 +40,11 @@ export declare class EurostatCatalogueService {
19
40
  * past its TTL that the refresh could not replace.
20
41
  */
21
42
  private refreshRetryAt;
43
+ /**
44
+ * The dimension value index a search that matches no catalogue text reads. Undefined until
45
+ * a TOC load starts the first index load.
46
+ */
47
+ private valueIndex;
22
48
  constructor(_config: AppConfig, _storage: StorageService);
23
49
  /**
24
50
  * Ensure a usable TOC is loaded. A cache younger than the configured TTL is
@@ -43,16 +69,28 @@ export declare class EurostatCatalogueService {
43
69
  * Only the TOC is required. A Comext list that fails to load leaves the catalogue
44
70
  * answering from the TOC alone: the failure is logged, and the merge is retried
45
71
  * after `REFRESH_RETRY_COOLDOWN_MS` without re-fetching the TOC.
72
+ *
73
+ * Every TOC load also starts the dimension value index load, which nothing awaits.
46
74
  */
47
75
  private fetchAndParseToc;
48
76
  /** Retry a failed Comext merge onto the TOC already held; concurrent callers share it. */
49
77
  private retryComextMerge;
50
78
  private logComextFailure;
79
+ /**
80
+ * Start a dimension value index load unless one is in flight, a failed load's backoff has
81
+ * not elapsed, or the index in service is younger than the TOC's TTL. Catalogue calls never
82
+ * wait for it: the load runs detached from the calling request and its trace, logs to the
83
+ * server log, and settles into the slot. A failure keeps the previous index in service and
84
+ * holds off the next attempt for `REFRESH_RETRY_COOLDOWN_MS`, doubling with each failure in
85
+ * a row up to the TOC's TTL.
86
+ */
87
+ private loadValueIndex;
51
88
  /**
52
89
  * Assemble a catalogue snapshot. `flows` undefined means the Comext list failed to
53
90
  * load, which arms the merge retry. `loadedAt` is the TOC's load time — the TTL and
54
- * the cursor generation both key on it. A later merge only appends entries, so a
55
- * cursor paged over the TOC alone still addresses the same leading matches.
91
+ * the cursor generation both key on it. A later merge only appends entries, and
92
+ * `search()` pages entries appended after a walk began behind the ones it began over, so
93
+ * a cursor paged over the TOC alone still pages every match once.
56
94
  */
57
95
  private buildCache;
58
96
  /** The Comext host's dataflow list — the `DS-*` collections the TOC does not carry. */
@@ -134,23 +172,46 @@ export declare class EurostatCatalogueService {
134
172
  * Decode a search cursor and confirm it belongs to this search. Malformed,
135
173
  * cross-query and superseded-snapshot cursors are rejected identically —
136
174
  * the caller's recovery is the same in all three cases, and the cursor is
137
- * opaque, so telling them apart would only describe its internal shape.
175
+ * opaque, so telling them apart would only describe its internal shape. `entryCount`,
176
+ * the snapshot's length when the walk began, can be no more than its length now.
177
+ * `valueIndex`, present on a walk over rows found through dimension values, is checked
178
+ * once `search()` knows which rows it pages.
138
179
  */
139
180
  private decodeSearchCursor;
181
+ /** One search result row for the TOC placement `entries[i]`. */
182
+ private toDatasetResult;
140
183
  /**
141
- * Each dataset's search text — label, breadcrumb, and code, lowercased, with whitespace
142
- * beside punctuation removed — indexed like `entries`. Folders, which search never
184
+ * Each dataset's search text, indexed like `entries`. Folders, which search never
143
185
  * returns, are undefined.
144
186
  */
145
187
  private buildSearchText;
146
188
  /**
147
189
  * For a query that matched nothing, the words whose removal alone finds matches, with
148
- * that count, in query order. `words` maps each distinct token to the word as typed.
149
- * One pass: a placement missing exactly one word rescues its code for that word, and a
150
- * code counts once per word whichever placement rescued it — so each count equals the
151
- * `totalMatches` of the same search without that word.
190
+ * that count (`wordRemovalCounts`), and the words no searched text contains at all
191
+ * (`unmatchedWords`, with `allWordsUnmatched` when that is every word), each in query
192
+ * order and each omitted when empty. `words` maps each distinct token to the word as
193
+ * typed. One pass: a placement missing exactly one word rescues its code for that
194
+ * word, and a code counts once per word whichever placement rescued it — so each count
195
+ * equals the `totalMatches` of the same search without that word.
196
+ *
197
+ * `unmatchedWords` is drawn from the first {@link MAX_UNMATCHED_WORD_CHECKS} distinct
198
+ * words. `unmatchedWordsPartial` is set when a word past them is held by no text the pass
199
+ * read, so it may be one no dataset carries.
152
200
  */
153
201
  private countWithoutEachWord;
202
+ /**
203
+ * The datasets a query that matched no catalogue text finds when a word may also occur
204
+ * at a word start of the English label of a value the metabase lists for the dataset.
205
+ * Every word must still be found, in the dataset's own text or in a value's label. Each
206
+ * code keeps its placement whose text holds the most words, the first such in TOC order.
207
+ *
208
+ * Ordered by fewer words found only through values; then rows where one value's label
209
+ * carries all of those words; then {@link searchTierOf} over the tokens the dataset's text
210
+ * holds, in query order; then TOC order. `marks` holds, for each word found through
211
+ * values, which labels carry it. `words` are the query's distinct tokens, at most
212
+ * {@link MAX_VALUE_SEARCH_WORDS}.
213
+ */
214
+ private searchValues;
154
215
  /**
155
216
  * Search datasets by keyword. The query is tokenized on whitespace and every
156
217
  * token must match (AND), case-insensitively, somewhere in a combined
@@ -165,27 +226,52 @@ export declare class EurostatCatalogueService {
165
226
  * several TOC branches keeps its first matching placement as the canonical
166
227
  * `themePath`, so totals and page slots count unique query targets.
167
228
  *
229
+ * Matches are ordered by {@link searchTierOf} over the tokens — label phrase, then
230
+ * every word in label or code, then breadcrumb-only — and by that first matching
231
+ * placement within a tier. A tier reads the label and code alone, so it is the same
232
+ * whichever placement supplied the `themePath`.
233
+ *
168
234
  * Results are paginated with an opaque cursor (`limit` = page size, capped at
169
235
  * 100) bound to the normalized query and the catalogue snapshot that produced
170
236
  * it. An unusable cursor — malformed, from another query, or from a catalogue
171
237
  * since refreshed — is rejected as `invalid_cursor` instead of silently paging
172
- * a different result set.
238
+ * a different result set. A Comext merge that lands mid-walk keeps the snapshot,
239
+ * so the cursor also carries the snapshot's length when the walk began: the
240
+ * datasets the merge appended page after every match the walk began over, each
241
+ * match still once.
242
+ *
243
+ * When no dataset's text holds every token, {@link searchValues} looks for the tokens
244
+ * the text lacks in the English labels of the dataset's dimension values. Its rows
245
+ * carry `matchedValues` and the result `matchedThroughValues`, and their cursor also
246
+ * binds the value index snapshot (`valueIndex`), so an index refresh mid-walk rejects it
247
+ * like a catalogue refresh. No search waits for the index: until one has loaded,
248
+ * `valuesNotSearched` is `index_unavailable`; past {@link MAX_VALUE_SEARCH_WORDS}
249
+ * distinct tokens it is `too_many_words`.
173
250
  *
174
251
  * An empty match reports the `DS-*` codes the query names that neither source lists
175
252
  * (`undisseminatedCodes`), so the caller can be told the collection is not
176
253
  * disseminated rather than to broaden the search, and — for two or more distinct
177
- * words — each word whose removal alone finds matches (`wordRemovalCounts`).
178
- * `comextListMissing` flags that the Comext list is not merged right now, so the
179
- * `DS-*` collections were not searched and absence from that list proves nothing;
180
- * `catalogueLoadedAt` marks a catalogue a failed refresh could not replace.
254
+ * words — each word whose removal alone finds matches (`wordRemovalCounts`) and each
255
+ * word no dataset's search text contains (`unmatchedWords`, as first typed), with
256
+ * `allWordsUnmatched` when that is every word. `unmatchedWords` reads the first
257
+ * {@link MAX_UNMATCHED_WORD_CHECKS} distinct words; `unmatchedWordsPartial` flags a query
258
+ * with a later word that may be one no dataset carries. `comextListMissing` flags that the
259
+ * Comext list is not merged right now, so the `DS-*` collections were not searched and
260
+ * absence from that list proves nothing; `catalogueLoadedAt` marks a catalogue a
261
+ * failed refresh could not replace.
181
262
  */
182
263
  search(query: string, limit: number, cursor: string | undefined, ctx: Context): Promise<{
264
+ allWordsUnmatched?: true;
183
265
  catalogueLoadedAt?: string;
184
266
  comextListMissing?: boolean;
185
267
  datasets: DatasetResult[];
268
+ matchedThroughValues?: true;
186
269
  nextCursor?: string;
187
270
  totalMatches: number;
188
271
  undisseminatedCodes?: string[];
272
+ unmatchedWords?: string[];
273
+ unmatchedWordsPartial?: true;
274
+ valuesNotSearched?: ValuesNotSearched;
189
275
  wordRemovalCounts?: Array<{
190
276
  totalMatches: number;
191
277
  word: string;
@@ -1 +1 @@
1
- {"version":3,"file":"eurostat-catalogue-service.d.ts","sourceRoot":"","sources":["../../../src/services/eurostat-catalogue/eurostat-catalogue-service.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,wBAAwB,CAAC;AACtD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAO/D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAgBrE,OAAO,KAAK,EAAE,UAAU,EAAE,aAAa,EAAY,MAAM,YAAY,CAAC;AAoEtE,qBAAa,wBAAwB;IACnC,OAAO,CAAC,KAAK,CAAuB;IACpC,qFAAqF;IACrF,OAAO,CAAC,OAAO,CAAgC;IAC/C,uDAAuD;IACvD,OAAO,CAAC,OAAO,CAAgC;IAC/C;;;;OAIG;IACH,OAAO,CAAC,cAAc,CAAK;IAK3B,YAAY,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,cAAc,EAAI;IAE5D;;;;;;;;;;;;;;OAcG;IACH,OAAO,CAAC,YAAY;YAIN,UAAU;IAyCxB;;;;;;OAMG;YACW,gBAAgB;IAY9B,0FAA0F;IAC1F,OAAO,CAAC,gBAAgB;IAoBxB,OAAO,CAAC,gBAAgB;IAUxB;;;;;OAKG;IACH,OAAO,CAAC,UAAU;IAclB,uFAAuF;YACzE,gBAAgB;IA4B9B;;;;;;;OAOG;IACH,OAAO,CAAC,gBAAgB;YA0CV,eAAe;IAmC7B;;;;;;;;;OASG;IACH,OAAO,CAAC,cAAc;IAQtB;;;;;OAKG;IACH,OAAO,CAAC,QAAQ;IAwEhB,OAAO,CAAC,OAAO;IAWf,OAAO,CAAC,YAAY;IASpB,OAAO,CAAC,SAAS;IAMjB;;OAEG;IACH,OAAO,CAAC,SAAS;IAYjB,wDAAwD;IACxD,OAAO,CAAC,YAAY;IAOpB;;;;;;OAMG;IACH,OAAO,CAAC,gBAAgB;IAUxB;;;OAGG;IACH,OAAO,CAAC,SAAS;IAIjB;;;;;;;;;;;;;OAaG;IACG,MAAM,CACV,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,GAAG,EAAE,OAAO,GACX,OAAO,CAAC;QACT,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAC5B,KAAK,EAAE,UAAU,EAAE,CAAC;QACpB,eAAe,CAAC,EAAE,MAAM,EAAE,EAAE,CAAC;QAC7B,UAAU,EAAE,MAAM,EAAE,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;KACpB,CAAC,CA4ED;IAED,OAAO,CAAC,YAAY;IAepB;;;;;OAKG;IACH,OAAO,CAAC,kBAAkB;IAkB1B;;;;OAIG;IACH,OAAO,CAAC,eAAe;IAUvB;;;;;;OAMG;IACH,OAAO,CAAC,oBAAoB;IAyB5B;;;;;;;;;;;;;;;;;;;;;;;;;;;OA2BG;IACG,MAAM,CACV,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,GAAG,EAAE,OAAO,GACX,OAAO,CAAC;QACT,iBAAiB,CAAC,EAAE,MAAM,CAAC;QAC3B,iBAAiB,CAAC,EAAE,OAAO,CAAC;QAC5B,QAAQ,EAAE,aAAa,EAAE,CAAC;QAC1B,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;QAC/B,iBAAiB,CAAC,EAAE,KAAK,CAAC;YAAE,YAAY,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC,CAAC;KACnE,CAAC,CAuED;CACF;AAgBD,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,GAAG,IAAI,CAE7F;AAED,wBAAgB,2BAA2B,IAAI,wBAAwB,CAOtE"}
1
+ {"version":3,"file":"eurostat-catalogue-service.d.ts","sourceRoot":"","sources":["../../../src/services/eurostat-catalogue/eurostat-catalogue-service.ts"],"names":[],"mappings":"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"}