@delali/narsil 0.2.2-next.29 → 0.2.3-next.32

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 (66) hide show
  1. package/README.md +12 -9
  2. package/dist/adapters/filesystem.d.ts +1 -1
  3. package/dist/adapters/filesystem.mjs +1 -1
  4. package/dist/adapters/indexeddb.d.ts +1 -1
  5. package/dist/adapters/indexeddb.mjs +1 -1
  6. package/dist/adapters/memory.d.ts +1 -1
  7. package/dist/{adapters-CVqI5NBt.d.ts → adapters-79OIa4xm.d.ts} +1 -1
  8. package/dist/brute-force-DbHYCTc3.d.ts +8 -0
  9. package/dist/chunk-BFIH7OV5.mjs +185 -0
  10. package/dist/chunk-C6VVLMRX.mjs +63 -0
  11. package/dist/{chunk-UNJZ7ZDB.mjs → chunk-EMI63EXP.mjs} +33 -2
  12. package/dist/chunk-MFFAJ2NR.mjs +135 -0
  13. package/dist/chunk-OBXS7OZM.mjs +376 -0
  14. package/dist/{chunk-ASI6AOW2.mjs → chunk-RO4EFWE6.mjs} +7833 -3524
  15. package/dist/{chunk-WLR5BFL3.mjs → chunk-TEAJO7CU.mjs} +3067 -2087
  16. package/dist/{chunk-S7RJJMHI.mjs → chunk-WDL632CN.mjs} +699 -222
  17. package/dist/{chunk-BKAI2WXI.mjs → chunk-WTONLDU3.mjs} +5 -0
  18. package/dist/client-DQHB_swQ.d.ts +793 -0
  19. package/dist/client.d.ts +6 -0
  20. package/dist/client.mjs +843 -0
  21. package/dist/{config-DXypXAfN.d.ts → config-ChZ7lfqc.d.ts} +3 -3
  22. package/dist/direct-executor-YARCDMJF.mjs +8 -0
  23. package/dist/distribution/coordinator/etcd.d.ts +3 -3
  24. package/dist/distribution/coordinator/etcd.mjs +471 -2
  25. package/dist/distribution/coordinator/in-memory.d.ts +3 -3
  26. package/dist/distribution/coordinator/in-memory.mjs +286 -1
  27. package/dist/distribution/transport/grpc.d.ts +45 -0
  28. package/dist/distribution/transport/grpc.mjs +586 -0
  29. package/dist/distribution/transport/in-memory.d.ts +118 -0
  30. package/dist/distribution/transport/in-memory.mjs +214 -0
  31. package/dist/distribution/transport/tcp.d.ts +27 -0
  32. package/dist/distribution/transport/tcp.mjs +595 -0
  33. package/dist/distribution.d.ts +241 -192
  34. package/dist/distribution.mjs +6620 -4795
  35. package/dist/embeddings/openai.d.ts +1 -1
  36. package/dist/embeddings/openai.mjs +1 -1
  37. package/dist/{engine-CO9Wnfie.d.ts → engine-DScGlT2Z.d.ts} +30 -3
  38. package/dist/index.browser.mjs +10035 -3914
  39. package/dist/index.d.ts +8 -8
  40. package/dist/index.mjs +8 -5
  41. package/dist/invalidation/broadcast-channel.d.ts +1 -1
  42. package/dist/invalidation/filesystem.d.ts +1 -1
  43. package/dist/invalidation/filesystem.mjs +3 -1
  44. package/dist/invalidation/noop.d.ts +1 -1
  45. package/dist/options-BORJg5XB.d.ts +234 -0
  46. package/dist/persistence/durability/checkpoint-worker.d.ts +4 -2
  47. package/dist/persistence/durability/checkpoint-worker.mjs +8 -5
  48. package/dist/react.d.ts +340 -0
  49. package/dist/react.mjs +687 -0
  50. package/dist/{schema-CE6S_aAr.d.ts → schema-emTQfEiX.d.ts} +21 -7
  51. package/dist/{search-DLBtiPdQ.d.ts → search-CQ-9bKxo.d.ts} +226 -14
  52. package/dist/server.d.ts +42 -356
  53. package/dist/server.mjs +493 -106
  54. package/dist/tasks-CnMLpfk-.d.ts +274 -0
  55. package/dist/types-BQDlIvfS.d.ts +34 -0
  56. package/dist/{types-BV3nAKTL.d.ts → types-Bfhhnh3G.d.ts} +23 -1
  57. package/dist/types-D5OwhtsQ.d.ts +97 -0
  58. package/dist/vector/hnsw-build-worker.d.ts +2 -7
  59. package/dist/vector/hnsw-build-worker.mjs +2 -1
  60. package/dist/vector/search-worker.d.ts +373 -0
  61. package/dist/vector/search-worker.mjs +279 -0
  62. package/dist/workers/entry.mjs +43 -25
  63. package/package.json +42 -2
  64. package/dist/chunk-FKK76OR7.mjs +0 -456
  65. package/dist/chunk-RQLXC2YS.mjs +0 -269
  66. package/dist/direct-executor-3W4QRA4E.mjs +0 -5
package/README.md CHANGED
@@ -12,11 +12,11 @@ Distributed search, reforged.
12
12
 
13
13
  Narsil is a distributed search engine with full-text, vector, hybrid, and geosearch. One codebase runs in two contexts: embedded in your application process, where queries answer without a network hop, and as a standalone search server with a REST API, a write-ahead log, and bulk NDJSON ingest. Both contexts run the same engine and store indexes in the same cross-language binary format (.nrsl), so an index built in one loads in the other.
14
14
 
15
- The engine partitions large indexes across workers and merges partition results into a single ranked answer. Its BM25 ranking matches the Anserini reference within 0.005 nDCG@10 on the BEIR datasets. On BEIR SciFact it ranks level with Elasticsearch and OpenSearch at 0.678 nDCG@10 and answers 1,020 keyword queries per second, about a quarter more than either ([benchmarks](https://github.com/assetcorp/narsil/blob/main/BENCHMARKS.md)). This TypeScript package is the reference implementation of the cross-language `.nrsl` format, and a second-language port in Go or Rust is the headline item on the [roadmap](https://github.com/assetcorp/narsil/blob/main/ROADMAP.md).
15
+ The engine partitions large indexes across workers and merges partition results into a single ranked answer. Its BM25 ranking matches the Anserini reference within 0.006 nDCG@10 on the BEIR datasets. On BEIR SciFact it takes the top nDCG@10 at 0.681, narrowly ahead of Elasticsearch and OpenSearch at 0.679, and answers 958 keyword queries per second against their 841 and 878 ([benchmarks](https://github.com/assetcorp/narsil/blob/main/BENCHMARKS.md)). This TypeScript package is the reference implementation of the cross-language `.nrsl` format, and a second-language port in Go or Rust is the headline item on the [roadmap](https://github.com/assetcorp/narsil/blob/main/ROADMAP.md).
16
16
 
17
17
  Try it in your browser at [narsil.sondelali.com/demo](https://narsil.sondelali.com/demo). Read the full documentation at [narsil.sondelali.com/docs](https://narsil.sondelali.com/docs).
18
18
 
19
- > *narsil* is the sword of Elendil in Tolkien's Lord of the Rings, shattered into shards and later reforged. The name maps to the architecture: data shatters into partitions, each shard is independently persisted, and every query reforges them into a unified result.
19
+ > *narsil* is the sword of Elendil in Tolkien's Lord of the Rings, shattered into shards and later reforged. The name maps to the architecture: data shatters into partitions, the engine persists each shard on its own, and every query reforges them into one ranked answer.
20
20
 
21
21
  ## Contents
22
22
 
@@ -79,7 +79,7 @@ const results = await narsil.query('products', {
79
79
  })
80
80
  ```
81
81
 
82
- Every hit carries the document, its id, and its BM25 score. `results.count` reports how many documents matched in total, and `results.elapsed` reports the query time in milliseconds.
82
+ Every hit holds the document, its id, and its BM25 score. `results.count` reports how many documents matched in total, and `results.elapsed` reports the query time in milliseconds.
83
83
 
84
84
  ## Features
85
85
 
@@ -93,7 +93,7 @@ Every hit carries the document, its id, and its BM25 score. `results.count` repo
93
93
 
94
94
  **Scale.** [Partitioned indexes](https://github.com/assetcorp/narsil/blob/main/docs/partitions-and-workers.md) route documents by deterministic hash and reshape online through `rebalance()`, with writes buffering in a write-ahead queue during the reshape. Worker promotion moves search off the main thread once document counts cross a threshold.
95
95
 
96
- **Operations.** The [HTTP server](https://github.com/assetcorp/narsil/blob/main/docs/http-server.md) subpath wraps an engine in a REST API with health probes, bulk NDJSON import, snapshot and restore endpoints, and task-based long operations. [Events, plugins, and memory reporting](https://github.com/assetcorp/narsil/blob/main/docs/observability.md) cover observability, and [language modules](https://github.com/assetcorp/narsil/blob/main/docs/language-support.md) cover 107 languages as separate entry points, 20 of them African.
96
+ **Operations.** The [HTTP server](https://github.com/assetcorp/narsil/blob/main/docs/http-server.md) subpath wraps an engine in a REST API with health probes, bulk NDJSON import, snapshot and restore endpoints, and task-based long operations. The [client](https://github.com/assetcorp/narsil/blob/main/docs/client.md) subpath reaches every one of those routes from a browser or from Node under the engine's own method names, and the [React](https://github.com/assetcorp/narsil/blob/main/docs/react.md) subpath gives those methods to components as hooks. [Events, plugins, and memory reporting](https://github.com/assetcorp/narsil/blob/main/docs/observability.md) cover observability, and [language modules](https://github.com/assetcorp/narsil/blob/main/docs/language-support.md) cover 107 languages as separate entry points, 20 of them African.
97
97
 
98
98
  ## Documentation
99
99
 
@@ -110,7 +110,10 @@ Every hit carries the document, its id, and its BM25 score. `results.count` repo
110
110
  | [Persistence and durability](../../docs/persistence-and-durability.md) | Storage backends, the write-ahead log, checkpoints, recovery, and snapshots |
111
111
  | [Partitions and workers](../../docs/partitions-and-workers.md) | Partition routing, online rebalancing, worker promotion, and multi-instance invalidation |
112
112
  | [Language support](../../docs/language-support.md) | The 107 language modules, analysis revisions and rebuilds, and named tokenizers and stop words |
113
- | [HTTP server](../../docs/http-server.md) | Wrapping an engine in a REST API, and every route it serves |
113
+ | [HTTP server](../../docs/http-server.md) | Wrapping an engine in a REST API, every route it serves, and long-running tasks |
114
+ | [Cluster mode](../../docs/cluster.md) | Multi-node indexes: nodes and roles, replication, routed writes, distributed searches and reads, and what a cluster refuses |
115
+ | [Client](../../docs/client.md) | Reaching a server from a browser or Node, following a task, and the codes it raises |
116
+ | [React](../../docs/react.md) | The hooks over the client, one shared request per key, and loading a corpus from a component |
114
117
  | [Observability](../../docs/observability.md) | Plugin hooks, engine events, and memory reporting |
115
118
  | [Errors](../../docs/errors.md) | Every error code and what throws it |
116
119
 
@@ -122,15 +125,15 @@ The [specification](../spec/) defines the `.nrsl` format, the analysis pipeline,
122
125
  | --- | --- |
123
126
  | [HTTP server](examples/http-server/README.md) | The launcher runs the engine as a REST service with durability, API-key auth, and Docker packaging, and its README documents the full API surface. |
124
127
  | [Browser](examples/browser/README.md) | The app embeds the engine in a browser with IndexedDB persistence and Web Worker search. |
125
- | [Server app](examples/server-app/README.md) | The app pairs a search UI with the HTTP server, including dataset loading and an embedding-backed Ask view. |
128
+ | [Server app](examples/server-app/README.md) | The app reaches the HTTP server through the client SDK and the React hooks, loads corpora as import tasks, and answers questions from them in an Ask view. |
126
129
 
127
130
  ## Distribution
128
131
 
129
- `@delali/narsil/distribution` holds the building blocks of Narsil's multi-node cluster mode: node roles, replication, coordinator adapters, and query routing. The distribution layer is under active development and highly experimental. It currently runs only in-process, its APIs change without notice, and it is not ready for production deployments. The design is specified in [`packages/spec/distribution`](../spec/distribution), and this section will grow into full documentation once the cluster mode is runnable.
132
+ `@delali/narsil/distribution` holds Narsil's multi-node cluster mode: nodes and roles, replication, coordinator adapters for etcd and in-process testing, TCP and gRPC transports with mutual TLS, and distributed query routing. A cluster node creates, drops, clears, writes, updates, searches, lists, counts, and suggests across every partition, and the [cluster example](examples/cluster) runs three node processes against etcd and survives a kill. The layer is experimental and its APIs change without notice, so pin an exact version before you depend on it. The [cluster guide](../../docs/cluster.md) covers the surface, and [`packages/spec/distribution`](../spec/distribution) specifies the contract every implementation follows.
130
133
 
131
134
  ## Search quality
132
135
 
133
- Ranking quality is measured against the [BEIR](https://github.com/beir-cellar/beir) SciFact corpus, 5,183 documents with 300 judged queries, where a human relevance judgment scores each query-document pair. Narsil runs in one process against Orama and MiniSearch, and every engine uses identical stop words (Lucene English, 35 terms), Porter stemming, and default BM25 parameters. Narsil takes the top nDCG@10 of the three.
136
+ Ranking quality is measured against the [BEIR](https://github.com/beir-cellar/beir) SciFact corpus, 5,183 documents with 300 judged queries, where a human relevance judgment scores each query-document pair. Narsil runs in one process against Orama and MiniSearch, and every engine uses identical stop words (Lucene English, 33 terms) and default BM25 parameters, while each one stems English with its own implementation. Narsil takes the top nDCG@10 of the three.
134
137
 
135
138
  **What these metrics mean:**
136
139
 
@@ -154,7 +157,7 @@ Narsil also runs as a search server. On the BEIR information-retrieval datasets
154
157
  | Deno | Web Workers | Filesystem | BroadcastChannel |
155
158
  | Browser | Web Workers | IndexedDB | BroadcastChannel |
156
159
 
157
- The [browser example](examples/browser/README.md) shows an embedded engine with IndexedDB persistence, and the [server app example](examples/server-app/README.md) shows a full search UI backed by the HTTP server.
160
+ The [browser example](examples/browser/README.md) shows an embedded engine with IndexedDB persistence, and the [server app example](examples/server-app/README.md) shows the same UI over the client SDK and the React hooks.
158
161
 
159
162
  ## License
160
163
 
@@ -1,4 +1,4 @@
1
- import { b as PersistenceAdapter } from '../adapters-CVqI5NBt.js';
1
+ import { P as PersistenceAdapter } from '../adapters-79OIa4xm.js';
2
2
 
3
3
  /**
4
4
  * Where {@link createFilesystemPersistence} writes its partitions.
@@ -1,4 +1,4 @@
1
- import { NarsilError, ErrorCodes } from '../chunk-UNJZ7ZDB.mjs';
1
+ import { NarsilError, ErrorCodes } from '../chunk-EMI63EXP.mjs';
2
2
 
3
3
  // src/persistence/filesystem.ts
4
4
  var cachedFs = null;
@@ -1,4 +1,4 @@
1
- import { b as PersistenceAdapter } from '../adapters-CVqI5NBt.js';
1
+ import { P as PersistenceAdapter } from '../adapters-79OIa4xm.js';
2
2
 
3
3
  /**
4
4
  * Which IndexedDB database and object store
@@ -1,4 +1,4 @@
1
- import { NarsilError, ErrorCodes } from '../chunk-UNJZ7ZDB.mjs';
1
+ import { NarsilError, ErrorCodes } from '../chunk-EMI63EXP.mjs';
2
2
 
3
3
  // src/persistence/indexeddb.ts
4
4
  var DEFAULT_DB_NAME = "narsil";
@@ -1,4 +1,4 @@
1
- import { b as PersistenceAdapter } from '../adapters-CVqI5NBt.js';
1
+ import { P as PersistenceAdapter } from '../adapters-79OIa4xm.js';
2
2
 
3
3
  /**
4
4
  * Builds a persistence adapter that keeps every partition in a map, which is
@@ -146,4 +146,4 @@ interface EmbeddingAdapter {
146
146
  shutdown?(): Promise<void>;
147
147
  }
148
148
 
149
- export type { EmbeddingAdapter as E, InvalidationAdapter as I, PartitionStatistics as P, InvalidationEvent as a, PersistenceAdapter as b };
149
+ export type { EmbeddingAdapter as E, InvalidationAdapter as I, PersistenceAdapter as P, InvalidationEvent as a, PartitionStatistics as b };
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Similarity metric a vector search ranks by.
3
+ *
4
+ * @internal
5
+ */
6
+ type VectorMetric = 'cosine' | 'dotProduct' | 'euclidean';
7
+
8
+ export type { VectorMetric as V };
@@ -0,0 +1,185 @@
1
+ // src/core/ordering/code-points.ts
2
+ function adjustUtf16Unit(unit) {
3
+ if (unit < 55296) return unit;
4
+ if (unit < 57344) return unit + 8192;
5
+ return unit - 2048;
6
+ }
7
+ function compareCodePoints(a, b) {
8
+ const shorter = a.length < b.length ? a.length : b.length;
9
+ let i = 0;
10
+ while (i < shorter && a.charCodeAt(i) === b.charCodeAt(i)) i++;
11
+ if (i === shorter) return a.length - b.length;
12
+ return adjustUtf16Unit(a.charCodeAt(i)) - adjustUtf16Unit(b.charCodeAt(i));
13
+ }
14
+
15
+ // src/core/ordering/fold-table.ts
16
+ var SINGLE_FOLDS = "1t,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;2j,lj;b,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;2,w;1,w;1,w;1,w;1,w;1,w;1,w;y,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;4,1;2,1;2,1;3,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;3,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,-3d;1,1;2,1;2,1;2,-7g;2,5u;1,1;2,1;2,5q;1,1;2,5p;1,5p;1,1;3,27;1,5m;1,5n;1,1;2,5p;1,5r;2,5v;1,5t;1,1;4,5v;1,5x;2,5y;1,1;2,1;2,1;2,62;1,1;2,62;3,1;2,62;1,1;2,61;1,61;1,1;2,1;2,63;1,1;4,1;8,2;1,1;2,2;1,1;2,2;1,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;3,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;3,2;1,1;2,1;2,-2p;1,-1k;1,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,-3m;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;8,8bv;1,1;2,-4j;1,8bs;3,1;2,-5f;1,1x;1,1z;1,1;2,1;2,1;2,1;2,1;6v,38;17,1;2,1;4,1;9,38;7,12;2,11;1,11;1,11;2,1s;2,1r;1,1r;2,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;2,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;n,1;d,8;1,-u;1,-p;4,-f;1,-m;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,-1i;1,-1c;3,-1o;1,-1s;2,1;2,-7;1,1;3,-3m;1,-3m;1,-3m;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,28;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1d,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;a,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,f;1,1;2,1;2,1;2,1;2,1;2,1;2,1;3,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;3,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;28a,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;1,5ls;2,5ls;6,5ls;mj,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1oj,-4su;1,-4st;1,-4sk;1,-4si;1,-4si;1,-4sj;1,-4sc;1,-4ro;1,r7n;1,1;7,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;1,-2bk;3,-2bk;1,-2bk;1,-2bk;8x,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;7,-1m;5,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;a,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1,-8;9,-8;1,-8;1,-8;1,-8;1,-8;1,-8;b,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1,-8;9,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1,-8;9,-8;1,-8;1,-8;1,-8;1,-8;1,-8;c,-8;2,-8;2,-8;2,-8;9,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1,-8;1,-8;21,-8;1,-8;1,-22;1,-22;3,-5j9;a,-2e;1,-2e;1,-2e;1,-2e;d,-8;1,-8;1,-2s;1,-2s;d,-8;1,-8;1,-34;1,-34;1,-7;c,-3k;1,-3k;1,-3i;1,-3i;8b,-5st;4,-6gv;1,-6di;7,s;1a,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;1,g;k,1;mr,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1,q;1f5,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1,1c;1d,1;2,-8af;1,-2xy;1,-89z;3,1;2,1;2,1;2,-8bg;1,-8al;1,-8bj;1,-8bi;2,1;3,1;9,-8cf;1,-8cf;1,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;9,1;2,1;5,1;nym,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;k,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;3s,1;2,1;2,1;2,1;2,1;2,1;2,1;4,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;b,1;2,1;2,-r9g;1,1;2,1;2,1;2,1;2,1;5,1;2,-wmg;3,1;2,1;4,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,-wn8;1,-wnj;1,-wnf;1,-wn5;1,-wn8;2,-wlu;1,-wmi;1,-wlx;1,ps;1,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,-1c;1,-wn7;1,-raw;1,1;2,1;2,-wo7;1,1;2,1;2,1;2,1;2,1;2,1;2,1;2,1;2,-wu9;p,1;or,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;1,-tzk;ggy,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;xy,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;3t,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;1,14;4d,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;2,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;1,13;2,13;1,13;1,13;1,13;1,13;1,13;1,13;2,13;1,13;1d7,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;1,1s;4e,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;27v,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;gw1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1,w;1t,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;1,r;o5k,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;1,y;";
17
+ var MULTI_FOLDS = "67,37,37;29,2x,lj;p,jg,32;4n,2y,lo;bk,qh,lk,ld;w,qt,lk,ld;d3,12d,136;4y7,2w,mp;1,38,lk;1,3b,lm;1,3d,lm;1,2p,ji;4,37,37;4y,qt,lv;2,qt,lv,lc;2,qt,lv,ld;2,qt,lv,n6;16,64g,qh;1,64h,qh;1,64i,qh;1,64j,qh;1,64k,qh;1,64l,qh;1,64m,qh;1,64n,qh;1,64g,qh;1,64h,qh;1,64i,qh;1,64j,qh;1,64k,qh;1,64l,qh;1,64m,qh;1,64n,qh;1,65c,qh;1,65d,qh;1,65e,qh;1,65f,qh;1,65g,qh;1,65h,qh;1,65i,qh;1,65j,qh;1,65c,qh;1,65d,qh;1,65e,qh;1,65f,qh;1,65g,qh;1,65h,qh;1,65i,qh;1,65j,qh;1,674,qh;1,675,qh;1,676,qh;1,677,qh;1,678,qh;1,679,qh;1,67a,qh;1,67b,qh;1,674,qh;1,675,qh;1,676,qh;1,677,qh;1,678,qh;1,679,qh;1,67a,qh;1,67b,qh;3,67k,qh;1,q9,qh;1,q4,qh;2,q9,n6;1,q9,n6,qh;5,q9,qh;6,67o,qh;1,qf,qh;1,q6,qh;2,qf,n6;1,qf,n6,qh;5,qf,qh;6,qh,lk,lc;1,qh,lk,ld;3,qh,n6;1,qh,lk,n6;b,qt,lk,lc;1,qt,lk,ld;1,qp,lv;2,qt,n6;1,qt,lk,n6;b,67w,qh;1,qx,qh;1,r2,qh;2,qx,n6;1,qx,n6,qh;5,qx,qh;179g,2u,2u;1,2u,2x;1,2u,30;1,2u,2u,2x;1,2u,2u,30;1,37,38;1,37,38;d,12s,12u;1,12s,12d;1,12s,12j;1,132,12u;1,12s,12l;";
18
+ var singleTable = null;
19
+ var multiTable = null;
20
+ function singleFoldTable() {
21
+ if (singleTable === null) {
22
+ singleTable = /* @__PURE__ */ new Map();
23
+ let source = 0;
24
+ for (const entry of SINGLE_FOLDS.split(";")) {
25
+ if (entry.length === 0) continue;
26
+ const [delta, offset] = entry.split(",");
27
+ source += Number.parseInt(delta, 36);
28
+ singleTable.set(source, source + Number.parseInt(offset, 36));
29
+ }
30
+ }
31
+ return singleTable;
32
+ }
33
+ function multiFoldTable() {
34
+ if (multiTable === null) {
35
+ multiTable = /* @__PURE__ */ new Map();
36
+ let source = 0;
37
+ for (const entry of MULTI_FOLDS.split(";")) {
38
+ if (entry.length === 0) continue;
39
+ const parts = entry.split(",");
40
+ source += Number.parseInt(parts[0], 36);
41
+ multiTable.set(
42
+ source,
43
+ parts.slice(1).map((cp) => Number.parseInt(cp, 36))
44
+ );
45
+ }
46
+ }
47
+ return multiTable;
48
+ }
49
+
50
+ // src/core/ordering/fold-compare.ts
51
+ var EXHAUSTED = -1;
52
+ function nextFoldedCodePoint(text, cursor, single, multi) {
53
+ if (cursor.pending !== null) {
54
+ const cp2 = cursor.pending[cursor.pendingIndex];
55
+ cursor.pendingIndex++;
56
+ if (cursor.pendingIndex === cursor.pending.length) {
57
+ cursor.pending = null;
58
+ cursor.pendingIndex = 0;
59
+ }
60
+ return cp2;
61
+ }
62
+ if (cursor.index >= text.length) return EXHAUSTED;
63
+ let cp = text.charCodeAt(cursor.index);
64
+ cursor.index++;
65
+ if (cp < 128) {
66
+ return cp >= 65 && cp <= 90 ? cp + 32 : cp;
67
+ }
68
+ if (cp >= 55296 && cp < 56320 && cursor.index < text.length) {
69
+ const low = text.charCodeAt(cursor.index);
70
+ if (low >= 56320 && low < 57344) {
71
+ cp = 65536 + (cp - 55296 << 10) + (low - 56320);
72
+ cursor.index++;
73
+ }
74
+ }
75
+ const mapped = single.get(cp);
76
+ if (mapped !== void 0) return mapped;
77
+ const expansion = multi.get(cp);
78
+ if (expansion === void 0) return cp;
79
+ if (expansion.length > 1) {
80
+ cursor.pending = expansion;
81
+ cursor.pendingIndex = 1;
82
+ }
83
+ return expansion[0];
84
+ }
85
+ function compareCaseFolded(a, b) {
86
+ const shorter = a.length < b.length ? a.length : b.length;
87
+ let start = 0;
88
+ while (start < shorter && a.charCodeAt(start) === b.charCodeAt(start)) start++;
89
+ if (start === a.length && start === b.length) return 0;
90
+ if (start > 0) {
91
+ const previous = a.charCodeAt(start - 1);
92
+ if (previous >= 55296 && previous < 56320) start--;
93
+ }
94
+ const single = singleFoldTable();
95
+ const multi = multiFoldTable();
96
+ const aCursor = { index: start, pending: null, pendingIndex: 0 };
97
+ const bCursor = { index: start, pending: null, pendingIndex: 0 };
98
+ for (; ; ) {
99
+ const aCp = nextFoldedCodePoint(a, aCursor, single, multi);
100
+ const bCp = nextFoldedCodePoint(b, bCursor, single, multi);
101
+ if (aCp !== bCp) return aCp - bCp;
102
+ if (aCp === EXHAUSTED) return 0;
103
+ }
104
+ }
105
+ function compareSortStrings(a, b) {
106
+ const folded = compareCaseFolded(a, b);
107
+ if (folded !== 0) return folded;
108
+ return compareCodePoints(a, b);
109
+ }
110
+
111
+ // src/core/ordering/sort-values.ts
112
+ var SORT_VALUE_MAX_CODE_POINTS = 512;
113
+ function truncateSortString(value) {
114
+ if (value.length <= SORT_VALUE_MAX_CODE_POINTS) return value;
115
+ let index = 0;
116
+ let counted = 0;
117
+ while (index < value.length && counted < SORT_VALUE_MAX_CODE_POINTS) {
118
+ const unit = value.charCodeAt(index);
119
+ if (unit >= 55296 && unit < 56320 && index + 1 < value.length) {
120
+ const low = value.charCodeAt(index + 1);
121
+ if (low >= 56320 && low < 57344) index++;
122
+ }
123
+ index++;
124
+ counted++;
125
+ }
126
+ return value.slice(0, index);
127
+ }
128
+ function toComparableSortValue(value) {
129
+ if (typeof value === "string") return truncateSortString(value);
130
+ if (typeof value === "number") return Number.isFinite(value) ? value : null;
131
+ if (typeof value === "boolean") return value;
132
+ return null;
133
+ }
134
+ function readSortField(document, path) {
135
+ const segments = path.split(".");
136
+ let current = document;
137
+ for (const segment of segments) {
138
+ if (current === null || current === void 0 || typeof current !== "object") return void 0;
139
+ if (!Object.hasOwn(current, segment)) return void 0;
140
+ current = current[segment];
141
+ }
142
+ return current;
143
+ }
144
+ function typeRank(value) {
145
+ if (typeof value === "number") return 0;
146
+ if (typeof value === "string") return 1;
147
+ return 2;
148
+ }
149
+ function comparePresentValues(a, b) {
150
+ const rankDifference = typeRank(a) - typeRank(b);
151
+ if (rankDifference !== 0) return rankDifference;
152
+ if (typeof a === "number" && typeof b === "number") return a - b;
153
+ if (typeof a === "string" && typeof b === "string") return compareSortStrings(a, b);
154
+ if (a === b) return 0;
155
+ return a ? 1 : -1;
156
+ }
157
+ function compareComparableValues(a, b, direction) {
158
+ if (a === null && b === null) return 0;
159
+ if (a === null) return 1;
160
+ if (b === null) return -1;
161
+ const comparison = comparePresentValues(a, b);
162
+ if (comparison === 0) return 0;
163
+ return direction === "desc" ? -comparison : comparison;
164
+ }
165
+ function compareComparableKeys(aKey, bKey, directions) {
166
+ for (let i = 0; i < directions.length; i++) {
167
+ const comparison = compareComparableValues(aKey[i] ?? null, bKey[i] ?? null, directions[i]);
168
+ if (comparison !== 0) return comparison;
169
+ }
170
+ return 0;
171
+ }
172
+ function compareSortValues(aValues, bValues, directions) {
173
+ for (let i = 0; i < directions.length; i++) {
174
+ const a = toComparableSortValue(aValues[i]);
175
+ const b = toComparableSortValue(bValues[i]);
176
+ if (a === null && b === null) continue;
177
+ if (a === null) return 1;
178
+ if (b === null) return -1;
179
+ const comparison = comparePresentValues(a, b);
180
+ if (comparison !== 0) return directions[i] === "desc" ? -comparison : comparison;
181
+ }
182
+ return 0;
183
+ }
184
+
185
+ export { SORT_VALUE_MAX_CODE_POINTS, compareCodePoints, compareComparableKeys, compareComparableValues, compareSortValues, readSortField, toComparableSortValue };
@@ -0,0 +1,63 @@
1
+ // src/distribution/transport/types.ts
2
+ var DEFAULT_TRANSPORT_CONFIG = {
3
+ connectTimeout: 5e3,
4
+ requestTimeout: 3e4,
5
+ replicationTimeout: 1e4,
6
+ snapshotTimeout: 3e5
7
+ };
8
+ var MAX_MESSAGE_SIZE_BYTES = 67108864;
9
+ var TransportErrorCodes = {
10
+ CONNECT_FAILED: "TRANSPORT_CONNECT_FAILED",
11
+ TIMEOUT: "TRANSPORT_TIMEOUT",
12
+ MESSAGE_TOO_LARGE: "TRANSPORT_MESSAGE_TOO_LARGE",
13
+ DECODE_FAILED: "TRANSPORT_DECODE_FAILED",
14
+ PEER_UNAVAILABLE: "TRANSPORT_PEER_UNAVAILABLE"
15
+ };
16
+ var TransportError = class extends Error {
17
+ code;
18
+ details;
19
+ constructor(code, message, details) {
20
+ super(message);
21
+ this.name = "TransportError";
22
+ this.code = code;
23
+ this.details = details ?? {};
24
+ }
25
+ };
26
+ var ReplicationMessageTypes = {
27
+ FORWARD: "replication.forward",
28
+ FORWARD_BATCH: "replication.forward_batch",
29
+ ENTRY: "replication.entry",
30
+ ENTRY_BATCH: "replication.entry_batch",
31
+ ACK: "replication.ack",
32
+ SYNC_REQUEST: "replication.sync_request",
33
+ SYNC_ENTRIES: "replication.sync_entries",
34
+ SNAPSHOT_START: "replication.snapshot_start",
35
+ SNAPSHOT_CHUNK: "replication.snapshot_chunk",
36
+ SNAPSHOT_END: "replication.snapshot_end",
37
+ SNAPSHOT_SYNC_REQUEST: "replication.snapshot_sync_request",
38
+ INSYNC_REMOVE: "replication.insync_remove",
39
+ INSYNC_CONFIRM: "replication.insync_confirm"
40
+ };
41
+ var QueryMessageTypes = {
42
+ SEARCH: "query.search",
43
+ SEARCH_RESULT: "query.search_result",
44
+ FETCH: "query.fetch",
45
+ FETCH_RESULT: "query.fetch_result",
46
+ STATS: "query.stats",
47
+ STATS_RESULT: "query.stats_result",
48
+ COUNT: "query.count",
49
+ COUNT_RESULT: "query.count_result",
50
+ LIST: "query.list",
51
+ LIST_RESULT: "query.list_result",
52
+ SUGGEST: "query.suggest",
53
+ SUGGEST_RESULT: "query.suggest_result",
54
+ PREFLIGHT: "query.preflight",
55
+ PREFLIGHT_RESULT: "query.preflight_result"
56
+ };
57
+ var ClusterMessageTypes = {
58
+ PING: "cluster.ping",
59
+ PONG: "cluster.pong",
60
+ BOOTSTRAP_COMPLETE: "cluster.bootstrap_complete"
61
+ };
62
+
63
+ export { ClusterMessageTypes, DEFAULT_TRANSPORT_CONFIG, MAX_MESSAGE_SIZE_BYTES, QueryMessageTypes, ReplicationMessageTypes, TransportError, TransportErrorCodes };
@@ -10,6 +10,7 @@ var ErrorCodes = {
10
10
  DOC_VALIDATION_FAILED: "DOC_VALIDATION_FAILED",
11
11
  INDEX_NOT_FOUND: "INDEX_NOT_FOUND",
12
12
  INDEX_ALREADY_EXISTS: "INDEX_ALREADY_EXISTS",
13
+ INDEX_ORPHANED: "INDEX_ORPHANED",
13
14
  PARTITION_CORRUPTED: "PARTITION_CORRUPTED",
14
15
  PARTITION_REBALANCING_BACKPRESSURE: "PARTITION_REBALANCING_BACKPRESSURE",
15
16
  WORKER_CRASHED: "WORKER_CRASHED",
@@ -27,6 +28,7 @@ var ErrorCodes = {
27
28
  SEARCH_INVALID_FILTER: "SEARCH_INVALID_FILTER",
28
29
  SEARCH_INVALID_MODE: "SEARCH_INVALID_MODE",
29
30
  SEARCH_INVALID_CURSOR: "SEARCH_INVALID_CURSOR",
31
+ SEARCH_RESULT_WINDOW_EXCEEDED: "SEARCH_RESULT_WINDOW_EXCEEDED",
30
32
  LANGUAGE_NOT_SUPPORTED: "LANGUAGE_NOT_SUPPORTED",
31
33
  ENVELOPE_VERSION_MISMATCH: "ENVELOPE_VERSION_MISMATCH",
32
34
  ENVELOPE_INVALID_MAGIC: "ENVELOPE_INVALID_MAGIC",
@@ -41,6 +43,7 @@ var ErrorCodes = {
41
43
  QUERY_PARTIAL_FAILURE: "QUERY_PARTIAL_FAILURE",
42
44
  QUERY_NODE_TIMEOUT: "QUERY_NODE_TIMEOUT",
43
45
  QUERY_NO_ACTIVE_REPLICA: "QUERY_NO_ACTIVE_REPLICA",
46
+ CLUSTER_OPERATION_UNSUPPORTED: "CLUSTER_OPERATION_UNSUPPORTED",
44
47
  ALLOCATION_NO_DATA_NODES: "ALLOCATION_NO_DATA_NODES",
45
48
  ALLOCATION_INVALID_CONFIG: "ALLOCATION_INVALID_CONFIG",
46
49
  ALLOCATION_FAILED: "ALLOCATION_FAILED",
@@ -51,6 +54,7 @@ var ErrorCodes = {
51
54
  NODE_ALREADY_JOINED: "NODE_ALREADY_JOINED",
52
55
  NODE_NOT_JOINED: "NODE_NOT_JOINED",
53
56
  COORDINATOR_DEPENDENCY_MISSING: "COORDINATOR_DEPENDENCY_MISSING",
57
+ TRANSPORT_DEPENDENCY_MISSING: "TRANSPORT_DEPENDENCY_MISSING",
54
58
  REPLICATION_ENTRY_INVALID: "REPLICATION_ENTRY_INVALID",
55
59
  REPLICATION_INSYNC_REMOVAL_FAILED: "REPLICATION_INSYNC_REMOVAL_FAILED",
56
60
  REPLICATION_ROLLBACK_FAILED: "REPLICATION_ROLLBACK_FAILED",
@@ -89,6 +93,27 @@ var ErrorCodes = {
89
93
  SNAPSHOT_SYNC_NOT_ASSIGNED: "SNAPSHOT_SYNC_NOT_ASSIGNED",
90
94
  SNAPSHOT_SYNC_ABORTED: "SNAPSHOT_SYNC_ABORTED"
91
95
  };
96
+ var ServerErrorCodes = {
97
+ INVALID_REQUEST: "INVALID_REQUEST",
98
+ INVALID_JSON: "INVALID_JSON",
99
+ EMPTY_BODY: "EMPTY_BODY",
100
+ PAYLOAD_TOO_LARGE: "PAYLOAD_TOO_LARGE",
101
+ NOT_FOUND: "NOT_FOUND",
102
+ TASK_NOT_FOUND: "TASK_NOT_FOUND",
103
+ TASK_NOT_CANCELLABLE: "TASK_NOT_CANCELLABLE",
104
+ TASK_OWNED_BY_ANOTHER_INSTANCE: "TASK_OWNED_BY_ANOTHER_INSTANCE",
105
+ TOO_MANY_REQUESTS: "TOO_MANY_REQUESTS",
106
+ HOOK_ERROR: "HOOK_ERROR",
107
+ INTERNAL_ERROR: "INTERNAL_ERROR"
108
+ };
109
+ var ClientErrorCodes = {
110
+ CLIENT_CONNECTION_FAILED: "CLIENT_CONNECTION_FAILED",
111
+ CLIENT_REQUEST_TIMEOUT: "CLIENT_REQUEST_TIMEOUT",
112
+ CLIENT_REQUEST_ABORTED: "CLIENT_REQUEST_ABORTED",
113
+ CLIENT_INVALID_RESPONSE: "CLIENT_INVALID_RESPONSE",
114
+ CLIENT_TASK_TIMEOUT: "CLIENT_TASK_TIMEOUT",
115
+ CLIENT_UNEXPECTED_ERROR: "CLIENT_UNEXPECTED_ERROR"
116
+ };
92
117
  var NarsilError = class extends Error {
93
118
  /** This says which failure it is. */
94
119
  code;
@@ -97,7 +122,10 @@ var NarsilError = class extends Error {
97
122
  /**
98
123
  * Builds an error carrying a code the caller can branch on.
99
124
  *
100
- * @param code - The failure this error reports.
125
+ * @param code - The failure this error reports, from {@link ErrorCodes} for
126
+ * an engine failure, {@link ServerErrorCodes} for one the HTTP layer raised,
127
+ * or {@link ClientErrorCodes} for one that stopped a request from reaching a
128
+ * server.
101
129
  * @param message - Plain description, for a log or a person.
102
130
  * @param details - Values behind the failure, which reach
103
131
  * {@link NarsilError.details}.
@@ -112,5 +140,8 @@ var NarsilError = class extends Error {
112
140
  function createNarsilError(code, message, details) {
113
141
  return new NarsilError(code, message, details);
114
142
  }
143
+ function describeError(error) {
144
+ return error instanceof Error ? error.message : String(error);
145
+ }
115
146
 
116
- export { ErrorCodes, NarsilError, createNarsilError };
147
+ export { ClientErrorCodes, ErrorCodes, NarsilError, ServerErrorCodes, createNarsilError, describeError };
@@ -0,0 +1,135 @@
1
+ import { MAX_MESSAGE_SIZE_BYTES, TransportError, TransportErrorCodes } from './chunk-C6VVLMRX.mjs';
2
+ import { encode, decode } from '@msgpack/msgpack';
3
+
4
+ // src/distribution/transport/tcp/types.ts
5
+ var DEFAULT_TCP_CONFIG = {
6
+ host: "0.0.0.0",
7
+ port: 9300,
8
+ connectTimeout: 5e3,
9
+ requestTimeout: 3e4,
10
+ replicationTimeout: 1e4,
11
+ snapshotTimeout: 3e5,
12
+ maxConnections: 256
13
+ };
14
+ var LENGTH_PREFIX_BYTES = 4;
15
+ var FRAME_TYPE_REQUEST = 1;
16
+ var FRAME_TYPE_RESPONSE = 2;
17
+ var FRAME_TYPE_STREAM_CHUNK = 3;
18
+ var FRAME_TYPE_STREAM_END = 4;
19
+ function encodeFrame(frameType, requestId, data) {
20
+ const envelope = encode({ frameType, requestId, data });
21
+ const totalLength = envelope.byteLength;
22
+ if (totalLength > MAX_MESSAGE_SIZE_BYTES) {
23
+ throw new TransportError(
24
+ TransportErrorCodes.MESSAGE_TOO_LARGE,
25
+ `Encoded frame (${totalLength} bytes) exceeds the ${MAX_MESSAGE_SIZE_BYTES} byte limit`,
26
+ { payloadSize: totalLength }
27
+ );
28
+ }
29
+ const buffer = new Uint8Array(LENGTH_PREFIX_BYTES + totalLength);
30
+ const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
31
+ view.setUint32(0, totalLength, false);
32
+ buffer.set(envelope, LENGTH_PREFIX_BYTES);
33
+ return buffer;
34
+ }
35
+ function encodeTransportMessage(message) {
36
+ return new Uint8Array(
37
+ encode({
38
+ type: message.type,
39
+ sourceId: message.sourceId,
40
+ requestId: message.requestId,
41
+ payload: message.payload
42
+ })
43
+ );
44
+ }
45
+ function decodeTransportMessage(data) {
46
+ const decoded = decode(data);
47
+ return {
48
+ type: decoded.type,
49
+ sourceId: decoded.sourceId,
50
+ requestId: decoded.requestId,
51
+ payload: new Uint8Array(decoded.payload)
52
+ };
53
+ }
54
+ var BUFFER_LIMIT = MAX_MESSAGE_SIZE_BYTES + LENGTH_PREFIX_BYTES;
55
+ var FrameParser = class {
56
+ chunks = [];
57
+ totalLength = 0;
58
+ onFrame;
59
+ constructor(onFrame) {
60
+ this.onFrame = onFrame;
61
+ }
62
+ feed(data) {
63
+ this.totalLength += data.byteLength;
64
+ if (this.totalLength > BUFFER_LIMIT) {
65
+ const exceeded = this.totalLength;
66
+ this.chunks = [];
67
+ this.totalLength = 0;
68
+ throw new TransportError(
69
+ TransportErrorCodes.MESSAGE_TOO_LARGE,
70
+ `Accumulated buffer (${exceeded} bytes) exceeds the allowed limit`,
71
+ { accumulatedBytes: exceeded }
72
+ );
73
+ }
74
+ this.chunks.push(data);
75
+ let buffer = this.compact();
76
+ while (buffer.byteLength >= LENGTH_PREFIX_BYTES) {
77
+ const view = new DataView(buffer.buffer, buffer.byteOffset, buffer.byteLength);
78
+ const frameLength = view.getUint32(0, false);
79
+ if (frameLength > MAX_MESSAGE_SIZE_BYTES) {
80
+ this.chunks = [];
81
+ this.totalLength = 0;
82
+ throw new TransportError(
83
+ TransportErrorCodes.MESSAGE_TOO_LARGE,
84
+ `Incoming frame (${frameLength} bytes) exceeds the ${MAX_MESSAGE_SIZE_BYTES} byte limit`,
85
+ { payloadSize: frameLength }
86
+ );
87
+ }
88
+ const totalNeeded = LENGTH_PREFIX_BYTES + frameLength;
89
+ if (buffer.byteLength < totalNeeded) {
90
+ break;
91
+ }
92
+ const frameBytes = buffer.subarray(LENGTH_PREFIX_BYTES, totalNeeded);
93
+ buffer = buffer.subarray(totalNeeded);
94
+ try {
95
+ const decoded = decode(frameBytes);
96
+ this.onFrame({
97
+ frameType: decoded.frameType,
98
+ requestId: decoded.requestId,
99
+ data: new Uint8Array(decoded.data)
100
+ });
101
+ } catch (err) {
102
+ this.chunks = [];
103
+ this.totalLength = 0;
104
+ throw new TransportError(
105
+ TransportErrorCodes.DECODE_FAILED,
106
+ `Failed to decode frame: ${err instanceof Error ? err.message : String(err)}`
107
+ );
108
+ }
109
+ }
110
+ this.chunks = buffer.byteLength > 0 ? [buffer] : [];
111
+ this.totalLength = buffer.byteLength;
112
+ }
113
+ reset() {
114
+ this.chunks = [];
115
+ this.totalLength = 0;
116
+ }
117
+ compact() {
118
+ if (this.chunks.length === 0) {
119
+ return new Uint8Array(0);
120
+ }
121
+ if (this.chunks.length === 1) {
122
+ return this.chunks[0];
123
+ }
124
+ const combined = new Uint8Array(this.totalLength);
125
+ let offset = 0;
126
+ for (const chunk of this.chunks) {
127
+ combined.set(chunk, offset);
128
+ offset += chunk.byteLength;
129
+ }
130
+ this.chunks = [combined];
131
+ return combined;
132
+ }
133
+ };
134
+
135
+ export { DEFAULT_TCP_CONFIG, FRAME_TYPE_REQUEST, FRAME_TYPE_RESPONSE, FRAME_TYPE_STREAM_CHUNK, FRAME_TYPE_STREAM_END, FrameParser, decodeTransportMessage, encodeFrame, encodeTransportMessage };