@delali/narsil 0.2.4-next.55 → 0.3.0

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 (52) hide show
  1. package/README.md +39 -28
  2. package/dist/adapters/filesystem.mjs +1 -1
  3. package/dist/adapters/indexeddb.mjs +1 -1
  4. package/dist/{capabilities-DlYw0Ov0.d.ts → capabilities-DSsOGz6F.d.ts} +2 -2
  5. package/dist/{chunk-BH5SYB5W.mjs → chunk-24RXHMEL.mjs} +604 -150
  6. package/dist/{chunk-D2S642IV.mjs → chunk-3LHGNRYE.mjs} +1 -1
  7. package/dist/{chunk-TVT5V4E7.mjs → chunk-B2TFROFX.mjs} +299 -168
  8. package/dist/{chunk-L225SHNB.mjs → chunk-L6TNPLAR.mjs} +19 -5
  9. package/dist/{chunk-U2AL3SON.mjs → chunk-THYRHHO2.mjs} +3 -3
  10. package/dist/{chunk-NTZYA3SJ.mjs → chunk-U7KYW4BA.mjs} +3 -3
  11. package/dist/{chunk-FRQVMFY7.mjs → chunk-USKFU7J5.mjs} +1 -0
  12. package/dist/{chunk-4NVPQ6S5.mjs → chunk-UXNWQZST.mjs} +12 -3
  13. package/dist/{chunk-RGS7FMCB.mjs → chunk-VMRR3DQU.mjs} +74 -16
  14. package/dist/{chunk-2GWVQWGA.mjs → chunk-YMZCMH5M.mjs} +45 -1
  15. package/dist/{chunk-UTOFOJOR.mjs → chunk-YNVIUGF5.mjs} +6 -2
  16. package/dist/{chunk-5T6AOR37.mjs → chunk-ZNZBXMP5.mjs} +601 -60
  17. package/dist/{chunk-XNQAIO74.mjs → chunk-ZZT3EAUC.mjs} +177 -309
  18. package/dist/{client-CQUqt9Ir.d.ts → client-BQK6Tf6A.d.ts} +3 -3
  19. package/dist/client.d.ts +8 -8
  20. package/dist/client.mjs +1 -0
  21. package/dist/{config-CNas6wJH.d.ts → config-BhldZgaK.d.ts} +2 -2
  22. package/dist/{config-bXxnJrQc.d.ts → config-DmXULPa-.d.ts} +15 -7
  23. package/dist/direct-executor-ALAVE7FC.mjs +12 -0
  24. package/dist/distribution/coordinator/etcd.d.ts +2 -2
  25. package/dist/distribution/coordinator/etcd.mjs +2 -2
  26. package/dist/distribution/coordinator/in-memory.d.ts +2 -2
  27. package/dist/distribution/coordinator/in-memory.mjs +1 -1
  28. package/dist/distribution/transport/grpc.mjs +1 -1
  29. package/dist/distribution.d.ts +8 -8
  30. package/dist/distribution.mjs +382 -162
  31. package/dist/embeddings/openai.mjs +2 -2
  32. package/dist/{engine-Dj4I91Jv.d.ts → engine-CIOyFozK.d.ts} +15 -12
  33. package/dist/index.browser.mjs +1565 -528
  34. package/dist/index.d.ts +7 -7
  35. package/dist/index.mjs +11 -11
  36. package/dist/invalidation/filesystem.mjs +1 -1
  37. package/dist/{memory-xrXOZMbw.d.ts → memory-yFaVn2xZ.d.ts} +199 -107
  38. package/dist/persistence/durability/checkpoint-worker.d.ts +1 -1
  39. package/dist/persistence/durability/checkpoint-worker.mjs +11 -11
  40. package/dist/react.d.ts +6 -6
  41. package/dist/react.mjs +1 -0
  42. package/dist/{schema-mLpXZBEh.d.ts → schema-d5Afu03A.d.ts} +7 -2
  43. package/dist/server.d.ts +10 -10
  44. package/dist/server.mjs +10 -10
  45. package/dist/{tasks-Df73Tjgq.d.ts → tasks-CH2Dod8w.d.ts} +1 -1
  46. package/dist/{thread-5UP6MGED.mjs → thread-DYHEQRVY.mjs} +14 -10
  47. package/dist/{types-BTIVO8DI.d.ts → types-DAK7mnUZ.d.ts} +1 -1
  48. package/dist/vector/search-worker.d.ts +1 -1
  49. package/dist/vector/search-worker.mjs +4 -4
  50. package/dist/workers/entry.mjs +4 -4
  51. package/package.json +9 -9
  52. package/dist/direct-executor-RBA5O7EN.mjs +0 -12
@@ -1,5 +1,5 @@
1
- import { MAX_M } from './chunk-UTOFOJOR.mjs';
2
- import { NarsilError, ErrorCodes } from './chunk-FRQVMFY7.mjs';
1
+ import { MAX_M } from './chunk-YNVIUGF5.mjs';
2
+ import { NarsilError, ErrorCodes } from './chunk-USKFU7J5.mjs';
3
3
 
4
4
  // src/schema/constants.ts
5
5
  var MAX_NESTING_DEPTH = 4;
@@ -23,6 +23,9 @@ function isTextFieldType(fieldType) {
23
23
  return fieldType === "string" || fieldType === SORTABLE_TEXT_FIELD_TYPE;
24
24
  }
25
25
  var VECTOR_PATTERN = /^vector\[(\d+)]$/;
26
+ function isGeopointOrVectorType(fieldType) {
27
+ return fieldType === "geopoint" || fieldType !== void 0 && VECTOR_PATTERN.test(fieldType);
28
+ }
26
29
  var FIELD_NAME_PATTERN = /^[A-Za-z0-9_]+$/;
27
30
  var RESERVED_ROOT_FIELDS = /* @__PURE__ */ new Set(["id"]);
28
31
  var PROTOTYPE_POLLUTION_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype"]);
@@ -115,9 +118,13 @@ function flattenRecursive(schema, prefix, result) {
115
118
  }
116
119
  }
117
120
  }
121
+ var flattenedSchemas = /* @__PURE__ */ new WeakMap();
118
122
  function flattenSchema(schema) {
119
- const result = {};
123
+ const cached = flattenedSchemas.get(schema);
124
+ if (cached !== void 0) return cached;
125
+ const result = /* @__PURE__ */ Object.create(null);
120
126
  flattenRecursive(schema, "", result);
127
+ flattenedSchemas.set(schema, Object.freeze(result));
121
128
  return result;
122
129
  }
123
130
  function extractVectorFieldsFromSchema(schema) {
@@ -407,7 +414,7 @@ function collectExtraFields(doc, schema, prefix, extras) {
407
414
  for (const key of Object.keys(doc)) {
408
415
  if (key === "id") continue;
409
416
  const path = prefix ? `${prefix}.${key}` : key;
410
- if (!(key in schema)) {
417
+ if (!Object.hasOwn(schema, key)) {
411
418
  extras.push(path);
412
419
  continue;
413
420
  }
@@ -509,5 +516,12 @@ var MAX_SORT_FIELDS = 8;
509
516
  var MAX_SORT_FIELD_NAME_LENGTH = 255;
510
517
  var MAX_CURSOR_ANCHOR_CODE_POINTS = 512;
511
518
  var PREFIX_MAX_EXPANSIONS = 50;
519
+ var DEFAULT_FUZZY_PREFIX_LENGTH = 2;
520
+ var DEFAULT_MAX_PER_GROUP = 1;
521
+ var DEFAULT_RANK_CONSTANT = 60;
522
+ var MIN_RANK_CONSTANT = 1;
523
+ var DEFAULT_LINEAR_ALPHA = 0.5;
524
+ var MIN_LINEAR_ALPHA = 0;
525
+ var MAX_LINEAR_ALPHA = 1;
512
526
 
513
- export { DEFAULT_PAGE_SIZE, MAX_CURSOR_ANCHOR_CODE_POINTS, MAX_CURSOR_LENGTH, MAX_NESTING_DEPTH, MAX_SORT_FIELDS, MAX_SORT_FIELD_NAME_LENGTH, PREFIX_MAX_EXPANSIONS, PROTOTYPE_POLLUTION_KEYS, RESULT_WINDOW, SORTABLE_TEXT_FIELD_TYPE, VECTOR_PATTERN, extractVectorFieldsFromSchema, flattenSchema, isQuantizationMode, isStorageMode, isTextFieldType, validateDocument, validateDocumentStrict, validateRequiredFields, validateSchema, validateVectorPromotion, validateVectorStorage };
527
+ export { DEFAULT_FUZZY_PREFIX_LENGTH, DEFAULT_LINEAR_ALPHA, DEFAULT_MAX_PER_GROUP, DEFAULT_PAGE_SIZE, DEFAULT_RANK_CONSTANT, MAX_CURSOR_ANCHOR_CODE_POINTS, MAX_CURSOR_LENGTH, MAX_LINEAR_ALPHA, MAX_NESTING_DEPTH, MAX_SORT_FIELDS, MAX_SORT_FIELD_NAME_LENGTH, MIN_LINEAR_ALPHA, MIN_RANK_CONSTANT, PREFIX_MAX_EXPANSIONS, PROTOTYPE_POLLUTION_KEYS, RESULT_WINDOW, SORTABLE_TEXT_FIELD_TYPE, VECTOR_PATTERN, extractVectorFieldsFromSchema, flattenSchema, isGeopointOrVectorType, isQuantizationMode, isStorageMode, isTextFieldType, validateDocument, validateDocumentStrict, validateRequiredFields, validateSchema, validateVectorPromotion, validateVectorStorage };
@@ -1,7 +1,7 @@
1
1
  import { OSQ_STEPS, OSQ_GRID, OSQ_REFINE_ROUNDS, OSQ_REFINE_TOLERANCE, OSQ4_NARROW_DIMENSION_LIMIT, DEFAULT_OSQ4_NARROW_OVERSAMPLE, DEFAULT_OVERSAMPLE_BY_BITS, OSQ_QUERY_BITS, OSQ_LAMBDA } from './chunk-ZJ4CSAB2.mjs';
2
- import { COMPACTION_TOMBSTONE_RATIO, COMPACTION_ABSOLUTE_THRESHOLD, nativeSearchCoreIsEnabled, loadNativeCore, stopUsingTheNativeSearchCore, noteFallback, MAX_LAYER_CAP, PLACEMENT_ROOM_REQUESTS, INITIAL_LIST_CAPACITY, DEFAULT_EF_SEARCH, INITIAL_UPPER_SLOTS } from './chunk-UTOFOJOR.mjs';
3
- import { compareCodePoints } from './chunk-2GWVQWGA.mjs';
4
- import { NarsilError, ErrorCodes } from './chunk-FRQVMFY7.mjs';
2
+ import { COMPACTION_TOMBSTONE_RATIO, COMPACTION_ABSOLUTE_THRESHOLD, nativeSearchCoreIsEnabled, loadNativeCore, stopUsingTheNativeSearchCore, noteFallback, MAX_LAYER_CAP, PLACEMENT_ROOM_REQUESTS, INITIAL_LIST_CAPACITY, DEFAULT_EF_SEARCH, INITIAL_UPPER_SLOTS } from './chunk-YNVIUGF5.mjs';
3
+ import { compareCodePoints } from './chunk-YMZCMH5M.mjs';
4
+ import { NarsilError, ErrorCodes } from './chunk-USKFU7J5.mjs';
5
5
  import { readSync, closeSync, openSync } from 'fs';
6
6
 
7
7
  // src/vector/constants.ts
@@ -1,6 +1,6 @@
1
- import { MAX_PARTITION_COUNT, MAX_REPLICATION_FACTOR } from './chunk-4NVPQ6S5.mjs';
2
- import { MAX_INDEX_NAME_LENGTH, INDEX_NAME_PATTERN } from './chunk-D2S642IV.mjs';
3
- import { NarsilError, ErrorCodes } from './chunk-FRQVMFY7.mjs';
1
+ import { MAX_PARTITION_COUNT, MAX_REPLICATION_FACTOR } from './chunk-UXNWQZST.mjs';
2
+ import { MAX_INDEX_NAME_LENGTH, INDEX_NAME_PATTERN } from './chunk-3LHGNRYE.mjs';
3
+ import { NarsilError, ErrorCodes } from './chunk-USKFU7J5.mjs';
4
4
  import { encode, decode } from '@msgpack/msgpack';
5
5
 
6
6
  var INDEX_CONFIG_PREFIX = "_narsil/index/";
@@ -12,6 +12,7 @@ var ErrorCodes = {
12
12
  INDEX_ALREADY_EXISTS: "INDEX_ALREADY_EXISTS",
13
13
  INDEX_ORPHANED: "INDEX_ORPHANED",
14
14
  INDEX_REOPEN_CAPACITY_EXHAUSTED: "INDEX_REOPEN_CAPACITY_EXHAUSTED",
15
+ INSTANCE_SHUT_DOWN: "INSTANCE_SHUT_DOWN",
15
16
  PARTITION_CORRUPTED: "PARTITION_CORRUPTED",
16
17
  PARTITION_REBALANCING_BACKPRESSURE: "PARTITION_REBALANCING_BACKPRESSURE",
17
18
  WORKER_CRASHED: "WORKER_CRASHED",
@@ -1,5 +1,5 @@
1
- import { validateRequiredFields } from './chunk-L225SHNB.mjs';
2
- import { ErrorCodes, NarsilError } from './chunk-FRQVMFY7.mjs';
1
+ import { validateRequiredFields } from './chunk-L6TNPLAR.mjs';
2
+ import { ErrorCodes, NarsilError } from './chunk-USKFU7J5.mjs';
3
3
 
4
4
  // src/narsil/internals.ts
5
5
  var engineCores = /* @__PURE__ */ new WeakMap();
@@ -344,7 +344,16 @@ async function resolveVectorText(params, embeddingAdapter, signal, embeddingAdap
344
344
  if (params.vector.text.length === 0) {
345
345
  throw new NarsilError(ErrorCodes.DOC_VALIDATION_FAILED, "Vector query 'text' must not be empty");
346
346
  }
347
- const raw = await embeddingAdapter.embed(params.vector.text, "query", signal);
347
+ let raw;
348
+ try {
349
+ raw = await embeddingAdapter.embed(params.vector.text, "query", signal);
350
+ } catch (err) {
351
+ if (err instanceof NarsilError) throw err;
352
+ const message = err instanceof Error ? err.message : String(err);
353
+ throw new NarsilError(ErrorCodes.EMBEDDING_FAILED, `The embedding adapter cannot embed the query: ${message}`, {
354
+ cause: message
355
+ });
356
+ }
348
357
  if (!(raw instanceof Float32Array)) {
349
358
  throw new NarsilError(
350
359
  ErrorCodes.EMBEDDING_FAILED,
@@ -1,6 +1,6 @@
1
- import { MAX_SORT_FIELDS } from './chunk-L225SHNB.mjs';
2
- import { nativeSearchCoreIsEnabled, loadNativeCore } from './chunk-UTOFOJOR.mjs';
3
- import { NarsilError, ServerErrorCodes, ErrorCodes } from './chunk-FRQVMFY7.mjs';
1
+ import { MAX_SORT_FIELDS } from './chunk-L6TNPLAR.mjs';
2
+ import { nativeSearchCoreIsEnabled, loadNativeCore } from './chunk-YNVIUGF5.mjs';
3
+ import { NarsilError, ServerErrorCodes, ErrorCodes } from './chunk-USKFU7J5.mjs';
4
4
 
5
5
  // src/server/capabilities.ts
6
6
  var ASYNC_IMPORT_CAPABILITY = "documents.import.async";
@@ -68,14 +68,21 @@ function matchOrigin(cors, requestOrigin) {
68
68
  if (typeof cors.origin === "string") return cors.origin;
69
69
  return cors.origin.includes(requestOrigin) ? requestOrigin : null;
70
70
  }
71
- function writeCorsOrigin(res, cors, requestOrigin) {
71
+ function corsOriginHeaders(cors, requestOrigin) {
72
72
  const allowed = matchOrigin(cors, requestOrigin);
73
- if (!allowed) return;
74
- res.writeHeader("Access-Control-Allow-Origin", allowed);
75
- if (allowed !== "*") res.writeHeader("Vary", "Origin");
73
+ const variesByOrigin = Array.isArray(cors.origin);
74
+ if (!allowed) return variesByOrigin ? [["Vary", "Origin"]] : [];
75
+ if (!variesByOrigin) return [["Access-Control-Allow-Origin", allowed]];
76
+ return [
77
+ ["Access-Control-Allow-Origin", allowed],
78
+ ["Vary", "Origin"]
79
+ ];
80
+ }
81
+ function writeCorsOrigin(res, cors, requestOrigin) {
82
+ for (const [key, value] of corsOriginHeaders(cors, requestOrigin)) res.writeHeader(key, value);
76
83
  }
77
- function corsWriter(cors) {
78
- return (res, req) => writeCorsOrigin(res, cors, req.getHeader("origin"));
84
+ function corsHeaderReader(cors) {
85
+ return (req) => corsOriginHeaders(cors, req.getHeader("origin"));
79
86
  }
80
87
 
81
88
  // src/server/errors.ts
@@ -116,6 +123,7 @@ var STATUS_BY_CODE = {
116
123
  INDEX_ALREADY_EXISTS: 409,
117
124
  INDEX_ORPHANED: 409,
118
125
  INDEX_REOPEN_CAPACITY_EXHAUSTED: 503,
126
+ INSTANCE_SHUT_DOWN: 503,
119
127
  DOC_ALREADY_EXISTS: 409,
120
128
  PARTITION_REBALANCING_BACKPRESSURE: 409,
121
129
  PARTITION_CAPACITY_EXCEEDED: 409,
@@ -703,6 +711,54 @@ function decodePathParameter(raw) {
703
711
  return null;
704
712
  }
705
713
  }
714
+ function sinkWritingAfterStatus(res, headers) {
715
+ if (headers.length === 0) return res;
716
+ const sink = {
717
+ cork(callback) {
718
+ res.cork(callback);
719
+ return sink;
720
+ },
721
+ writeStatus(status) {
722
+ res.writeStatus(status);
723
+ for (const [key, value] of headers) res.writeHeader(key, value);
724
+ return sink;
725
+ },
726
+ writeHeader(key, value) {
727
+ res.writeHeader(key, value);
728
+ return sink;
729
+ },
730
+ end(body) {
731
+ res.end(body);
732
+ return sink;
733
+ },
734
+ endWithoutBody() {
735
+ res.endWithoutBody();
736
+ return sink;
737
+ },
738
+ tryEnd(body, totalSize) {
739
+ return res.tryEnd(body, totalSize);
740
+ },
741
+ getWriteOffset() {
742
+ return res.getWriteOffset();
743
+ },
744
+ onWritable(handler) {
745
+ res.onWritable(handler);
746
+ return sink;
747
+ },
748
+ onAborted(handler) {
749
+ res.onAborted(handler);
750
+ return sink;
751
+ },
752
+ onData(handler) {
753
+ res.onData(handler);
754
+ return sink;
755
+ },
756
+ getRemoteAddressAsText() {
757
+ return res.getRemoteAddressAsText();
758
+ }
759
+ };
760
+ return sink;
761
+ }
706
762
  function isDenial(value) {
707
763
  return typeof value === "object" && value !== null && "status" in value;
708
764
  }
@@ -726,13 +782,14 @@ function sendDenial(res, authorization) {
726
782
  sendError(res, authorization.denial.status, authorization.denial.code, authorization.denial.message);
727
783
  }
728
784
  function createRouteRunner(deps) {
729
- const { authorize, gate, writeCors } = deps;
785
+ const { authorize, gate, corsHeaders } = deps;
730
786
  return (handler, opts) => {
731
787
  const paramCount = opts.paramCount ?? 0;
732
788
  const needsBody = opts.needsBody ?? false;
733
789
  const useHook = authorize !== void 0 && !opts.skipHooks;
734
790
  const gated = !opts.skipHooks;
735
- return (res, req) => {
791
+ return (response, req) => {
792
+ const res = corsHeaders ? sinkWritingAfterStatus(response, corsHeaders(req)) : response;
736
793
  const params = [];
737
794
  let malformed = null;
738
795
  for (let i = 0; i < paramCount; i++) {
@@ -753,13 +810,12 @@ function createRouteRunner(deps) {
753
810
  headers[key] = value;
754
811
  });
755
812
  hookContext = {
756
- method: req.getMethod(),
813
+ method: req.getMethod().toUpperCase(),
757
814
  path: req.getUrl(),
758
815
  headers,
759
816
  remoteAddress: Buffer.from(res.getRemoteAddressAsText()).toString()
760
817
  };
761
818
  }
762
- if (writeCors) writeCors(res, req);
763
819
  const abort = initAbortHandler(res);
764
820
  if (malformed !== null) {
765
821
  sendError(
@@ -877,8 +933,10 @@ function registerServerRoutes(app, run, handlers, limits, cors) {
877
933
  for (const route of serverRoutes(limits)) {
878
934
  app[route.method](route.path, run(handlers[route.handler], route.options));
879
935
  }
880
- app.any("/*", (res) => {
881
- sendError(res, 404, ServerErrorCodes.NOT_FOUND, "Route not found");
936
+ const corsHeaders = cors ? corsHeaderReader(cors) : null;
937
+ app.any("/*", (res, req) => {
938
+ const sink = corsHeaders === null ? res : sinkWritingAfterStatus(res, corsHeaders(req));
939
+ sendError(sink, 404, ServerErrorCodes.NOT_FOUND, "Route not found");
882
940
  });
883
941
  }
884
942
 
@@ -916,4 +974,4 @@ function childAppOf(app) {
916
974
  return candidate;
917
975
  }
918
976
 
919
- export { ASYNC_IMPORT_CAPABILITY, DEFAULT_IMPORT_BATCH_SIZE, DEFAULT_MAX_BODY_BYTES, DEFAULT_MAX_CONCURRENT_REQUESTS, DEFAULT_MAX_CONCURRENT_TASKS, DEFAULT_MAX_FETCH_DOCUMENTS, DEFAULT_MAX_IMPORT_BYTES, DEFAULT_MAX_IMPORT_ERRORS, DEFAULT_MAX_LINE_BYTES, DEFAULT_MAX_RESULT_WINDOW, DEFAULT_MAX_RETAINED_TASKS, DEFAULT_MAX_TASK_PAGE_SIZE, DEFAULT_TASK_PAGE_SIZE, IMPORT_FLUSHES_IN_FLIGHT, INDEX_LIFECYCLE_CAPABILITY, INDEX_TOUCH_INTERVALS_PER_IDLE_TIMEOUT, MAIN_THREAD_GATE_SLOT, MAX_INDEX_TOUCH_INTERVAL_MS, MIN_COUNTED_SERVER_LIMIT, MIN_UNBOUNDED_SERVER_LIMIT, REBUILD_ANALYSIS_CAPABILITY, RUNNING_TASK_TTL_MS, SERVER_CAPABILITIES, TASK_CANCEL_CAPABILITY, TASK_FILTER_CAPABILITY, TASK_PROGRESS_WRITE_INTERVAL_MS, TERMINAL_TASK_TTL_MS, acceptorOf, authorizerFor, badRequest, childAppOf, clearGateSlot, corsWriter, createDocumentReadHandlers, createRouteRunner, createSharedGateBuffer, createSharedRequestGate, createVersionHandler, gateSlotOfWorker, httpStatusForNarsilError, loadUWebSockets, parseJson, parseJsonOptional, parseTaskListQuery, registerServerRoutes, rejectInvalid, resolveCors, respondError, respondJson, sendBinary, sendError, sendRelayed, serializeBatchResult, serializeNarsilError, serverRoutes, toHttpError, validateBatch, validateCreateIndex, validateDocumentBody, validateQuery, validateRebalance, validateSuggest, versionReport };
977
+ export { ASYNC_IMPORT_CAPABILITY, DEFAULT_IMPORT_BATCH_SIZE, DEFAULT_MAX_BODY_BYTES, DEFAULT_MAX_CONCURRENT_REQUESTS, DEFAULT_MAX_CONCURRENT_TASKS, DEFAULT_MAX_FETCH_DOCUMENTS, DEFAULT_MAX_IMPORT_BYTES, DEFAULT_MAX_IMPORT_ERRORS, DEFAULT_MAX_LINE_BYTES, DEFAULT_MAX_RESULT_WINDOW, DEFAULT_MAX_RETAINED_TASKS, DEFAULT_MAX_TASK_PAGE_SIZE, DEFAULT_TASK_PAGE_SIZE, IMPORT_FLUSHES_IN_FLIGHT, INDEX_LIFECYCLE_CAPABILITY, INDEX_TOUCH_INTERVALS_PER_IDLE_TIMEOUT, MAIN_THREAD_GATE_SLOT, MAX_INDEX_TOUCH_INTERVAL_MS, MIN_COUNTED_SERVER_LIMIT, MIN_UNBOUNDED_SERVER_LIMIT, REBUILD_ANALYSIS_CAPABILITY, RUNNING_TASK_TTL_MS, SERVER_CAPABILITIES, TASK_CANCEL_CAPABILITY, TASK_FILTER_CAPABILITY, TASK_PROGRESS_WRITE_INTERVAL_MS, TERMINAL_TASK_TTL_MS, acceptorOf, authorizerFor, badRequest, childAppOf, clearGateSlot, corsHeaderReader, createDocumentReadHandlers, createRouteRunner, createSharedGateBuffer, createSharedRequestGate, createVersionHandler, gateSlotOfWorker, httpStatusForNarsilError, loadUWebSockets, parseJson, parseJsonOptional, parseTaskListQuery, registerServerRoutes, rejectInvalid, resolveCors, respondError, respondJson, sendBinary, sendError, sendRelayed, serializeBatchResult, serializeNarsilError, serverRoutes, toHttpError, validateBatch, validateCreateIndex, validateDocumentBody, validateQuery, validateRebalance, validateSuggest, versionReport };
@@ -112,6 +112,16 @@ function compareSortStrings(a, b) {
112
112
  var SORT_VALUE_MAX_CODE_POINTS = 512;
113
113
 
114
114
  // src/core/ordering/sort-values.ts
115
+ var SORT_MODES = ["min", "max", "avg", "median"];
116
+ function isSortMode(value) {
117
+ return value === "min" || value === "max" || value === "avg" || value === "median";
118
+ }
119
+ function defaultSortMode(direction) {
120
+ return direction === "desc" ? "max" : "min";
121
+ }
122
+ function sortModeOf(entry) {
123
+ return entry.mode ?? defaultSortMode(entry.direction);
124
+ }
115
125
  function truncateSortString(value) {
116
126
  if (value.length <= SORT_VALUE_MAX_CODE_POINTS) return value;
117
127
  let index = 0;
@@ -133,6 +143,40 @@ function toComparableSortValue(value) {
133
143
  if (typeof value === "boolean") return value;
134
144
  return null;
135
145
  }
146
+ function numericReduction(values, mode) {
147
+ const numbers = [];
148
+ for (const element of values) {
149
+ if (typeof element === "number" && Number.isFinite(element)) numbers.push(element);
150
+ }
151
+ if (numbers.length === 0) return null;
152
+ if (mode === "avg") {
153
+ let mean = 0;
154
+ for (let index = 0; index < numbers.length; index++) {
155
+ mean += (numbers[index] - mean) / (index + 1);
156
+ }
157
+ return mean;
158
+ }
159
+ numbers.sort((a, b) => a - b);
160
+ const middle = numbers.length >> 1;
161
+ if (numbers.length % 2 === 1) return numbers[middle];
162
+ return numbers[middle - 1] / 2 + numbers[middle] / 2;
163
+ }
164
+ function toReducedSortValue(value, mode) {
165
+ if (!Array.isArray(value)) return toComparableSortValue(value);
166
+ if (mode === "avg" || mode === "median") return numericReduction(value, mode);
167
+ let chosen = null;
168
+ for (const element of value) {
169
+ const comparable = toComparableSortValue(element);
170
+ if (comparable === null) continue;
171
+ if (chosen === null) {
172
+ chosen = comparable;
173
+ continue;
174
+ }
175
+ const comparison = comparePresentValues(comparable, chosen);
176
+ if (mode === "min" ? comparison < 0 : comparison > 0) chosen = comparable;
177
+ }
178
+ return chosen;
179
+ }
136
180
  function readSortField(document, path) {
137
181
  const segments = path.split(".");
138
182
  let current = document;
@@ -184,4 +228,4 @@ function compareSortValues(aValues, bValues, directions) {
184
228
  return 0;
185
229
  }
186
230
 
187
- export { SORT_VALUE_MAX_CODE_POINTS, compareCodePoints, compareComparableKeys, compareComparableValues, compareSortValues, readSortField, toComparableSortValue };
231
+ export { SORT_MODES, SORT_VALUE_MAX_CODE_POINTS, compareCodePoints, compareComparableKeys, compareComparableValues, compareSortValues, defaultSortMode, isSortMode, readSortField, sortModeOf, toComparableSortValue, toReducedSortValue };
@@ -1,4 +1,4 @@
1
- import { NarsilError, ErrorCodes } from './chunk-FRQVMFY7.mjs';
1
+ import { NarsilError, ErrorCodes } from './chunk-USKFU7J5.mjs';
2
2
  import { existsSync } from 'fs';
3
3
  import { createRequire } from 'module';
4
4
  import { join, dirname } from 'path';
@@ -119,6 +119,10 @@ function coreAt(path) {
119
119
  }
120
120
  return core;
121
121
  }
122
+ function requireSearchBackendSettings() {
123
+ requestedBackend();
124
+ if (process.env.NARSIL_REQUIRE_NATIVE_CORE === "1") loadNativeCore();
125
+ }
122
126
  function loadNativeCore() {
123
127
  if (loaded !== void 0) return loaded;
124
128
  if (requestedBackend() === "wasm") {
@@ -132,4 +136,4 @@ function loadNativeCore() {
132
136
  return loaded;
133
137
  }
134
138
 
135
- export { COMPACTION_ABSOLUTE_THRESHOLD, COMPACTION_TOMBSTONE_RATIO, DEFAULT_EF_SEARCH, INITIAL_LIST_CAPACITY, INITIAL_UPPER_SLOTS, MAX_LAYER_CAP, MAX_M, PLACEMENT_ROOM_REQUESTS, loadNativeCore, nativeSearchCoreIsEnabled, noteFallback, stopUsingTheNativeSearchCore };
139
+ export { COMPACTION_ABSOLUTE_THRESHOLD, COMPACTION_TOMBSTONE_RATIO, DEFAULT_EF_SEARCH, INITIAL_LIST_CAPACITY, INITIAL_UPPER_SLOTS, MAX_LAYER_CAP, MAX_M, PLACEMENT_ROOM_REQUESTS, loadNativeCore, nativeSearchCoreIsEnabled, noteFallback, requireSearchBackendSettings, stopUsingTheNativeSearchCore };