@tmlmobilidade/interfaces 20260420.1455.19 → 20260421.1115.34

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.
@@ -271,9 +271,13 @@ function routeTermToField(term) {
271
271
  if (/^\d+_\d+_\d+$/.test(term)) {
272
272
  return { pattern_id: term };
273
273
  }
274
- // Exact trip_id match: "1001_0_2_0800_0829_0_26"
275
- if (/^\d+_\d+_\d+_\d+_\d+_\d+_\d+$/.test(term)) {
276
- return { trip_id: term };
274
+ // Wildcard trip_id: any string containing %%; %% → regex .*
275
+ // NOTE: case-sensitive (no $options: 'i') so anchored prefix regex can use
276
+ // the { trip_id: 1 } / { trip_id: 1, start_time_scheduled: 1 } index.
277
+ if (term.includes('%%')) {
278
+ let escaped = term.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
279
+ escaped = escaped.replace(/%%/g, '.*');
280
+ return { trip_id: { $regex: `^${escaped}$` } };
277
281
  }
278
282
  // route_id: "1001_0"
279
283
  if (/^\d+_\d+$/.test(term)) {
@@ -289,12 +293,6 @@ function routeTermToField(term) {
289
293
  const n = Number(term);
290
294
  if (term.length >= 3)
291
295
  return { line_id: n };
292
- if (term.length <= 2)
293
- return { agency_id: term };
294
- }
295
- // plan_id: uppercase alpha-numeric prefix like "KACZ2"
296
- if (/^[A-Z]+\d*$/.test(term)) {
297
- return { plan_id: term };
298
296
  }
299
297
  return null;
300
298
  }
@@ -331,10 +329,17 @@ function buildSearchPipeline(filter) {
331
329
  }
332
330
  }
333
331
  if (unroutableTerms.length > 0) {
334
- const pattern = unroutableTerms
335
- .map(k => `(?=.*${k.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')})`)
336
- .join('') + '.*';
337
- conditions.push({ _id: { $options: 'i', $regex: pattern } });
332
+ // Anchor first term as prefix on trip_id so the query can use the
333
+ // { trip_id: 1, start_time_scheduled: 1 } compound index.
334
+ // Remaining terms become plain contains-regex (no index, but bounded
335
+ // by the prefix scan of the first term).
336
+ // NOTE: case-sensitive; adding $options: 'i' disables index usage.
337
+ const escape = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
338
+ const [firstTerm, ...restTerms] = unroutableTerms;
339
+ conditions.push({ trip_id: { $regex: `^${escape(firstTerm)}` } });
340
+ for (const rest of restTerms) {
341
+ conditions.push({ trip_id: { $regex: escape(rest) } });
342
+ }
338
343
  }
339
344
  if (conditions.length === 1) {
340
345
  pipeline.push({ $match: conditions[0] });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tmlmobilidade/interfaces",
3
- "version": "20260420.1455.19",
3
+ "version": "20260421.1115.34",
4
4
  "author": {
5
5
  "email": "iso@tmlmobilidade.pt",
6
6
  "name": "TML-ISO"