graphile-search 1.5.6 → 1.5.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/esm/plugin.js +42 -21
  2. package/package.json +2 -2
  3. package/plugin.js +42 -21
package/esm/plugin.js CHANGED
@@ -104,6 +104,13 @@ export function createUnifiedSearchPlugin(options) {
104
104
  const { adapters, enableSearchScore = true, enableFullTextSearch = true } = options;
105
105
  // Per-codec cache of discovered columns, keyed by codec name
106
106
  const codecCache = new Map();
107
+ // Bridge between orderBy enum apply and filter apply.
108
+ // The orderBy enum runs on the PgSelectStep while the filter runs on
109
+ // a separate query-builder object. They share the same SQL `alias`
110
+ // reference, so we use a WeakMap keyed by that alias to pass the
111
+ // requested sort direction from the orderBy (which fires first) to
112
+ // the filter (which fires second and has the score expression).
113
+ const _pendingOrderDirections = new WeakMap();
107
114
  /**
108
115
  * Get (or compute) the adapter columns for a given codec.
109
116
  *
@@ -453,10 +460,18 @@ export function createUnifiedSearchPlugin(options) {
453
460
  codec: codec,
454
461
  attributeName: column.attributeName,
455
462
  });
456
- const metaKey = `unified_order_${adapter.name}_${baseFieldName}`;
463
+ const orderKey = `unified_order_${adapter.name}_${baseFieldName}`;
457
464
  const makePlan = (direction) => (step) => {
458
- if (typeof step.setMeta === 'function') {
459
- step.setMeta(metaKey, direction);
465
+ // Store the requested direction keyed by the SQL alias so
466
+ // the filter's apply (which runs second) can read it.
467
+ const aliasKey = step?.alias;
468
+ if (aliasKey) {
469
+ let dirs = _pendingOrderDirections.get(aliasKey);
470
+ if (!dirs) {
471
+ dirs = {};
472
+ _pendingOrderDirections.set(aliasKey, dirs);
473
+ }
474
+ dirs[orderKey] = direction;
460
475
  }
461
476
  };
462
477
  const ascName = inflection.pgSearchOrderByEnum(codec, column.attributeName, adapter.name, adapter.scoreSemantics.metric, true);
@@ -484,8 +499,14 @@ export function createUnifiedSearchPlugin(options) {
484
499
  const searchScoreAscName = inflection.constantCase('search_score_asc');
485
500
  const searchScoreDescName = inflection.constantCase('search_score_desc');
486
501
  const makeSearchScorePlan = (direction) => (step) => {
487
- if (typeof step.setMeta === 'function') {
488
- step.setMeta('unified_order_search_score', direction);
502
+ const aliasKey = step?.alias;
503
+ if (aliasKey) {
504
+ let dirs = _pendingOrderDirections.get(aliasKey);
505
+ if (!dirs) {
506
+ dirs = {};
507
+ _pendingOrderDirections.set(aliasKey, dirs);
508
+ }
509
+ dirs['unified_order_search_score'] = direction;
489
510
  }
490
511
  };
491
512
  newValues = build.extend(newValues, {
@@ -581,11 +602,11 @@ export function createUnifiedSearchPlugin(options) {
581
602
  qb.setMeta(scoreMetaKey, {
582
603
  selectIndex: scoreIndex,
583
604
  });
584
- }
585
- // ORDER BY: only add when explicitly requested
586
- if (qb && typeof qb.getMetaRaw === 'function') {
587
- const orderMetaKey = `unified_order_${adapter.name}_${baseFieldName}`;
588
- const explicitDir = qb.getMetaRaw(orderMetaKey);
605
+ // ORDER BY: read the direction stored by the orderBy
606
+ // enum (which ran first) via the shared alias key.
607
+ const orderKey = `unified_order_${adapter.name}_${baseFieldName}`;
608
+ const dirs = _pendingOrderDirections.get($condition.alias);
609
+ const explicitDir = dirs?.[orderKey];
589
610
  if (explicitDir) {
590
611
  qb.orderBy({
591
612
  fragment: result.scoreExpression,
@@ -647,17 +668,17 @@ export function createUnifiedSearchPlugin(options) {
647
668
  qb.setMeta(scoreMetaKey, {
648
669
  selectIndex: scoreIndex,
649
670
  });
650
- // ORDER BY: only add when explicitly requested via orderBy enum
651
- if (typeof qb.getMetaRaw === 'function') {
652
- const orderMetaKey = `unified_order_${adapter.name}_${baseFieldName}`;
653
- const explicitDir = qb.getMetaRaw(orderMetaKey);
654
- if (explicitDir) {
655
- qb.orderBy({
656
- fragment: result.scoreExpression,
657
- codec: TYPES.float,
658
- direction: explicitDir,
659
- });
660
- }
671
+ // ORDER BY: read the direction stored by the orderBy
672
+ // enum (which ran first) via the shared alias key.
673
+ const orderKey = `unified_order_${adapter.name}_${baseFieldName}`;
674
+ const dirs = _pendingOrderDirections.get($condition.alias);
675
+ const explicitDir = dirs?.[orderKey];
676
+ if (explicitDir) {
677
+ qb.orderBy({
678
+ fragment: result.scoreExpression,
679
+ codec: TYPES.float,
680
+ direction: explicitDir,
681
+ });
661
682
  }
662
683
  }
663
684
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "graphile-search",
3
- "version": "1.5.6",
3
+ "version": "1.5.7",
4
4
  "description": "Unified PostGraphile v5 search plugin — abstracts tsvector, BM25, pg_trgm, and pgvector behind a single adapter-based architecture with composite searchScore",
5
5
  "author": "Constructive <developers@constructive.io>",
6
6
  "homepage": "https://github.com/constructive-io/constructive",
@@ -62,5 +62,5 @@
62
62
  "hybrid-search",
63
63
  "searchScore"
64
64
  ],
65
- "gitHead": "0b7edbd088ca9661503c5038134ee15311eac027"
65
+ "gitHead": "fc23b83307d007a14e54b1d0fc36614b9650a5dc"
66
66
  }
package/plugin.js CHANGED
@@ -107,6 +107,13 @@ function createUnifiedSearchPlugin(options) {
107
107
  const { adapters, enableSearchScore = true, enableFullTextSearch = true } = options;
108
108
  // Per-codec cache of discovered columns, keyed by codec name
109
109
  const codecCache = new Map();
110
+ // Bridge between orderBy enum apply and filter apply.
111
+ // The orderBy enum runs on the PgSelectStep while the filter runs on
112
+ // a separate query-builder object. They share the same SQL `alias`
113
+ // reference, so we use a WeakMap keyed by that alias to pass the
114
+ // requested sort direction from the orderBy (which fires first) to
115
+ // the filter (which fires second and has the score expression).
116
+ const _pendingOrderDirections = new WeakMap();
110
117
  /**
111
118
  * Get (or compute) the adapter columns for a given codec.
112
119
  *
@@ -456,10 +463,18 @@ function createUnifiedSearchPlugin(options) {
456
463
  codec: codec,
457
464
  attributeName: column.attributeName,
458
465
  });
459
- const metaKey = `unified_order_${adapter.name}_${baseFieldName}`;
466
+ const orderKey = `unified_order_${adapter.name}_${baseFieldName}`;
460
467
  const makePlan = (direction) => (step) => {
461
- if (typeof step.setMeta === 'function') {
462
- step.setMeta(metaKey, direction);
468
+ // Store the requested direction keyed by the SQL alias so
469
+ // the filter's apply (which runs second) can read it.
470
+ const aliasKey = step?.alias;
471
+ if (aliasKey) {
472
+ let dirs = _pendingOrderDirections.get(aliasKey);
473
+ if (!dirs) {
474
+ dirs = {};
475
+ _pendingOrderDirections.set(aliasKey, dirs);
476
+ }
477
+ dirs[orderKey] = direction;
463
478
  }
464
479
  };
465
480
  const ascName = inflection.pgSearchOrderByEnum(codec, column.attributeName, adapter.name, adapter.scoreSemantics.metric, true);
@@ -487,8 +502,14 @@ function createUnifiedSearchPlugin(options) {
487
502
  const searchScoreAscName = inflection.constantCase('search_score_asc');
488
503
  const searchScoreDescName = inflection.constantCase('search_score_desc');
489
504
  const makeSearchScorePlan = (direction) => (step) => {
490
- if (typeof step.setMeta === 'function') {
491
- step.setMeta('unified_order_search_score', direction);
505
+ const aliasKey = step?.alias;
506
+ if (aliasKey) {
507
+ let dirs = _pendingOrderDirections.get(aliasKey);
508
+ if (!dirs) {
509
+ dirs = {};
510
+ _pendingOrderDirections.set(aliasKey, dirs);
511
+ }
512
+ dirs['unified_order_search_score'] = direction;
492
513
  }
493
514
  };
494
515
  newValues = build.extend(newValues, {
@@ -584,11 +605,11 @@ function createUnifiedSearchPlugin(options) {
584
605
  qb.setMeta(scoreMetaKey, {
585
606
  selectIndex: scoreIndex,
586
607
  });
587
- }
588
- // ORDER BY: only add when explicitly requested
589
- if (qb && typeof qb.getMetaRaw === 'function') {
590
- const orderMetaKey = `unified_order_${adapter.name}_${baseFieldName}`;
591
- const explicitDir = qb.getMetaRaw(orderMetaKey);
608
+ // ORDER BY: read the direction stored by the orderBy
609
+ // enum (which ran first) via the shared alias key.
610
+ const orderKey = `unified_order_${adapter.name}_${baseFieldName}`;
611
+ const dirs = _pendingOrderDirections.get($condition.alias);
612
+ const explicitDir = dirs?.[orderKey];
592
613
  if (explicitDir) {
593
614
  qb.orderBy({
594
615
  fragment: result.scoreExpression,
@@ -650,17 +671,17 @@ function createUnifiedSearchPlugin(options) {
650
671
  qb.setMeta(scoreMetaKey, {
651
672
  selectIndex: scoreIndex,
652
673
  });
653
- // ORDER BY: only add when explicitly requested via orderBy enum
654
- if (typeof qb.getMetaRaw === 'function') {
655
- const orderMetaKey = `unified_order_${adapter.name}_${baseFieldName}`;
656
- const explicitDir = qb.getMetaRaw(orderMetaKey);
657
- if (explicitDir) {
658
- qb.orderBy({
659
- fragment: result.scoreExpression,
660
- codec: pg_1.TYPES.float,
661
- direction: explicitDir,
662
- });
663
- }
674
+ // ORDER BY: read the direction stored by the orderBy
675
+ // enum (which ran first) via the shared alias key.
676
+ const orderKey = `unified_order_${adapter.name}_${baseFieldName}`;
677
+ const dirs = _pendingOrderDirections.get($condition.alias);
678
+ const explicitDir = dirs?.[orderKey];
679
+ if (explicitDir) {
680
+ qb.orderBy({
681
+ fragment: result.scoreExpression,
682
+ codec: pg_1.TYPES.float,
683
+ direction: explicitDir,
684
+ });
664
685
  }
665
686
  }
666
687
  }