@delali/narsil 0.1.7 → 0.1.8

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 (87) hide show
  1. package/README.md +44 -2
  2. package/dist/adapters/filesystem.d.ts +1 -1
  3. package/dist/adapters/filesystem.mjs +46 -2
  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-BbRkoiu9.d.ts → adapters-Bo2JQg8b.d.ts} +2 -1
  8. package/dist/chunk-ALB35PRQ.mjs +98 -0
  9. package/dist/{chunk-KHL4RPC3.mjs → chunk-FS7XLIUS.mjs} +2536 -2284
  10. package/dist/chunk-GQEHCZG7.mjs +6825 -0
  11. package/dist/chunk-KMMJMDUA.mjs +44 -0
  12. package/dist/chunk-RQLXC2YS.mjs +269 -0
  13. package/dist/chunk-S7RJJMHI.mjs +1086 -0
  14. package/dist/{chunk-I24SGLFS.mjs → chunk-TW6BXTOL.mjs} +5 -1
  15. package/dist/chunk-WISGW24C.mjs +455 -0
  16. package/dist/config-cQLlYR3U.d.ts +470 -0
  17. package/dist/direct-executor-FX56DYD3.mjs +4 -0
  18. package/dist/distribution/coordinator/etcd.d.ts +16 -0
  19. package/dist/distribution/coordinator/etcd.mjs +2 -0
  20. package/dist/distribution/coordinator/in-memory.d.ts +7 -0
  21. package/dist/distribution/coordinator/in-memory.mjs +1 -0
  22. package/dist/distribution.d.ts +122 -0
  23. package/dist/distribution.mjs +7410 -0
  24. package/dist/embeddings/openai.d.ts +1 -1
  25. package/dist/embeddings/openai.mjs +1 -1
  26. package/dist/index.browser.mjs +11469 -7481
  27. package/dist/index.d.ts +6 -450
  28. package/dist/index.mjs +7 -3236
  29. package/dist/invalidation/broadcast-channel.d.ts +1 -1
  30. package/dist/invalidation/filesystem.d.ts +1 -1
  31. package/dist/invalidation/noop.d.ts +1 -1
  32. package/dist/{language-ClUGLuoC.d.ts → language-ONQ3iVDf.d.ts} +1 -0
  33. package/dist/languages/arabic.d.ts +1 -1
  34. package/dist/languages/armenian.d.ts +1 -1
  35. package/dist/languages/bulgarian.d.ts +1 -1
  36. package/dist/languages/chinese.d.ts +1 -1
  37. package/dist/languages/dagbani.d.ts +1 -1
  38. package/dist/languages/danish.d.ts +1 -1
  39. package/dist/languages/dutch.d.ts +1 -1
  40. package/dist/languages/english.d.ts +1 -1
  41. package/dist/languages/english.mjs +1 -1
  42. package/dist/languages/ewe.d.ts +1 -1
  43. package/dist/languages/finnish.d.ts +1 -1
  44. package/dist/languages/french.d.ts +1 -1
  45. package/dist/languages/ga.d.ts +1 -1
  46. package/dist/languages/german.d.ts +1 -1
  47. package/dist/languages/greek.d.ts +1 -1
  48. package/dist/languages/hausa.d.ts +1 -1
  49. package/dist/languages/hindi.d.ts +1 -1
  50. package/dist/languages/hungarian.d.ts +1 -1
  51. package/dist/languages/igbo.d.ts +1 -1
  52. package/dist/languages/indonesian.d.ts +1 -1
  53. package/dist/languages/irish.d.ts +1 -1
  54. package/dist/languages/italian.d.ts +1 -1
  55. package/dist/languages/japanese.d.ts +1 -1
  56. package/dist/languages/nepali.d.ts +1 -1
  57. package/dist/languages/norwegian.d.ts +1 -1
  58. package/dist/languages/portuguese.d.ts +1 -1
  59. package/dist/languages/romanian.d.ts +1 -1
  60. package/dist/languages/russian.d.ts +1 -1
  61. package/dist/languages/sanskrit.d.ts +1 -1
  62. package/dist/languages/serbian.d.ts +1 -1
  63. package/dist/languages/slovenian.d.ts +1 -1
  64. package/dist/languages/spanish.d.ts +1 -1
  65. package/dist/languages/swahili.d.ts +1 -1
  66. package/dist/languages/swedish.d.ts +1 -1
  67. package/dist/languages/tamil.d.ts +1 -1
  68. package/dist/languages/turkish.d.ts +1 -1
  69. package/dist/languages/twi.d.ts +1 -1
  70. package/dist/languages/ukrainian.d.ts +1 -1
  71. package/dist/languages/yoruba.d.ts +1 -1
  72. package/dist/languages/zulu.d.ts +1 -1
  73. package/dist/narsil-ChTdkwPu.d.ts +68 -0
  74. package/dist/persistence/durability/checkpoint-worker.d.ts +41 -0
  75. package/dist/persistence/durability/checkpoint-worker.mjs +59 -0
  76. package/dist/schema-BVaw7nqz.d.ts +58 -0
  77. package/dist/serialization/crc32-worker.d.ts +20 -0
  78. package/dist/serialization/crc32-worker.mjs +61 -0
  79. package/dist/server.d.ts +218 -0
  80. package/dist/server.mjs +1185 -0
  81. package/dist/types-Bt7c4hDF.d.ts +73 -0
  82. package/dist/vector/hnsw-build-worker.mjs +1 -1
  83. package/dist/workers/entry.mjs +1 -1
  84. package/package.json +37 -2
  85. package/dist/chunk-R2C2EQGO.mjs +0 -53
  86. package/dist/chunk-VVORJOXR.mjs +0 -759
  87. package/dist/direct-executor-LBJLGMJ2.mjs +0 -4
package/README.md CHANGED
@@ -135,10 +135,50 @@ BM25 scoring with field boosting, fuzzy matching via bounded Levenshtein distanc
135
135
 
136
136
  Indexes split into shards when they grow beyond a configurable threshold. Partition assignment uses FNV-1a hashing for deterministic routing. Background rebalancing redistributes documents across new partitions without blocking queries, using a write-ahead queue for zero-downtime resharding.
137
137
 
138
+ **Single-process overhead.** Partitioning pays off when shards live on separate processes or hosts. Inside one Node.js process, going from 1 to 20 partitions costs about 14% of insert throughput, 28% of median search latency, and 27% at p95, with no scaling upside. Keep `partitions.maxPartitions` low (or unset) for single-process deployments and raise it once you fan partitions out across workers or distributed nodes.
139
+
140
+ **Rebalance latency spikes.** While a partition reshape is running, worst-tick p95 latency can climb to about 25ms compared with around 11ms in steady state. Schedule large bulk inserts that trigger rebalancing during low-traffic windows, or pre-size the index with `partitions.maxDocsPerPartition` to avoid mid-load reshapes.
141
+
138
142
  ### Worker isolation
139
143
 
140
144
  Search operations move off the main thread through worker threads (Node.js, Bun) or Web Workers (browser, Deno). The engine starts in direct mode for small indexes and auto-promotes to workers once document counts cross a threshold. You keep using the same API throughout.
141
145
 
146
+ ### Memory reporting
147
+
148
+ Narsil reports memory at three levels: per index, per partition, and per runtime. `getStats(indexName)` returns `estimatedMemoryBytes`, a formula-based estimate for the index's main-thread partitions and vector structures.
149
+
150
+ ```ts
151
+ const indexStats = narsil.getStats('products')
152
+
153
+ console.log(indexStats.estimatedMemoryBytes)
154
+ ```
155
+
156
+ The estimate comes from document counts, posting lists, field indexes, and vector indexes. It excludes V8 object headers, allocator overhead, and other host runtime costs, so use it for comparing indexes inside one process.
157
+
158
+ `getPartitionStats(indexName)` returns the same estimate for each partition. The partition values sum to `getStats(indexName).estimatedMemoryBytes`.
159
+
160
+ ```ts
161
+ const partitions = narsil.getPartitionStats('products')
162
+
163
+ for (const partition of partitions) {
164
+ console.log(partition.partitionId, partition.estimatedMemoryBytes)
165
+ }
166
+ ```
167
+
168
+ `getMemoryStats()` returns a runtime snapshot and worker reports. It is async because workers report their heap usage through the worker message channel.
169
+
170
+ ```ts
171
+ const memory = await narsil.getMemoryStats()
172
+
173
+ console.log(memory.estimatedIndexBytes)
174
+ console.log(memory.process?.heapUsed)
175
+ console.log(memory.workers)
176
+ ```
177
+
178
+ `memory.estimatedIndexBytes` sums `estimatedMemoryBytes` across every index in this Narsil instance. `memory.process` comes from `process.memoryUsage()` when the runtime exposes it. It measures the whole host process, so two Narsil instances in one Node.js process report the same process numbers. Browser runtimes return `null` for `memory.process`.
179
+
180
+ `memory.workers` lists `heapUsed`, `heapTotal`, and `external` for each active worker. The array is empty before worker promotion.
181
+
142
182
  ### Distributed BM25 scoring
143
183
 
144
184
  Three scoring modes handle the partition-skew problem:
@@ -149,7 +189,7 @@ Three scoring modes handle the partition-skew problem:
149
189
 
150
190
  ### Vector search
151
191
 
152
- Store and query high-dimensional embeddings with cosine similarity, dot product, or Euclidean distance. Small vector sets use brute-force linear scan. When a field exceeds 10,000 vectors, the engine builds an HNSW graph in the background and swaps the search backend transparently.
192
+ Store and query high-dimensional embeddings with cosine similarity, dot product, or Euclidean distance. Small vector sets use an exact brute-force scan. Once a field crosses 1,024 vectors, the engine builds an HNSW graph and switches the field to approximate search. The threshold is configurable per index via `vectorPromotion.threshold`.
153
193
 
154
194
  ### Hybrid search
155
195
 
@@ -356,7 +396,7 @@ Ranking quality is measured against the [Cranfield Collection](https://ir-datase
356
396
 
357
397
  | Engine | nDCG@10 | P@10 | MAP | MRR |
358
398
  | --- | ---: | ---: | ---: | ---: |
359
- | **Narsil 0.1.1** | **0.3739** | **0.2458** | **0.2614** | **0.5638** |
399
+ | **Narsil** | **0.3739** | **0.2458** | **0.2614** | **0.5638** |
360
400
  | Orama 3.1.18 | 0.2911 | 0.1836 | 0.1846 | 0.4821 |
361
401
  | MiniSearch 7.2.0 | 0.0077 | 0.0067 | 0.0027 | 0.0139 |
362
402
 
@@ -371,6 +411,8 @@ These scores fall within the expected range for BM25 on standard IR benchmarks (
371
411
 
372
412
  Reproduce: `pnpm -C packages/benchmarks bench --tiers quality`
373
413
 
414
+ Narsil also runs as a search server. On the BEIR information-retrieval datasets it is measured against Elasticsearch, OpenSearch, Qdrant, Weaviate, Typesense, and Meilisearch across keyword, vector, and hybrid retrieval. See [the full benchmarks](https://github.com/assetcorp/narsil/blob/main/BENCHMARKS.md) for those results.
415
+
374
416
  ## Runtime support (TypeScript)
375
417
 
376
418
  | Runtime | Concurrency | Persistence | Invalidation |
@@ -1,4 +1,4 @@
1
- import { P as PersistenceAdapter } from '../adapters-BbRkoiu9.js';
1
+ import { b as PersistenceAdapter } from '../adapters-Bo2JQg8b.js';
2
2
 
3
3
  interface FilesystemPersistenceConfig {
4
4
  directory: string;
@@ -1,4 +1,4 @@
1
- import { NarsilError, ErrorCodes } from '../chunk-R2C2EQGO.mjs';
1
+ import { NarsilError, ErrorCodes } from '../chunk-ALB35PRQ.mjs';
2
2
 
3
3
  // src/persistence/filesystem.ts
4
4
  var cachedFs = null;
@@ -30,6 +30,25 @@ async function resolveAndGuard(baseDir, key) {
30
30
  }
31
31
  return resolvedPath;
32
32
  }
33
+ async function fsyncDirectory(dirPath, fs) {
34
+ let handle = null;
35
+ try {
36
+ handle = await fs.open(dirPath, "r");
37
+ await handle.sync();
38
+ } catch (err) {
39
+ const code = err.code;
40
+ if (code === "EISDIR" || code === "EPERM" || code === "EINVAL" || code === "ENOTSUP") {
41
+ return;
42
+ }
43
+ throw new NarsilError(ErrorCodes.PERSISTENCE_FSYNC_FAILED, `fsync failed for directory "${dirPath}"`, {
44
+ cause: err instanceof Error ? err.message : String(err)
45
+ });
46
+ } finally {
47
+ if (handle !== null) {
48
+ await handle.close().catch(() => void 0);
49
+ }
50
+ }
51
+ }
33
52
  async function listDirectoryRecursive(dir, baseDir, pathMod, fs) {
34
53
  const results = [];
35
54
  let entries;
@@ -62,13 +81,38 @@ function createFilesystemPersistence(config) {
62
81
  }
63
82
  const baseDir = config.directory;
64
83
  return {
84
+ directory: baseDir,
65
85
  async save(key, data) {
66
86
  const resolvedPath = await resolveAndGuard(baseDir, key);
67
87
  const fs = await getFs();
68
88
  const pathMod = await getPath();
69
89
  const dir = pathMod.dirname(resolvedPath);
70
90
  await fs.mkdir(dir, { recursive: true });
71
- await fs.writeFile(resolvedPath, data);
91
+ const tempName = `${pathMod.basename(resolvedPath)}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(36).slice(2)}`;
92
+ const tempPath = pathMod.join(dir, tempName);
93
+ let handle = null;
94
+ try {
95
+ handle = await fs.open(tempPath, "w");
96
+ await handle.write(data);
97
+ try {
98
+ await handle.sync();
99
+ } catch (err) {
100
+ throw new NarsilError(ErrorCodes.PERSISTENCE_FSYNC_FAILED, `fsync failed for "${key}"`, {
101
+ key,
102
+ cause: err instanceof Error ? err.message : String(err)
103
+ });
104
+ }
105
+ await handle.close();
106
+ handle = null;
107
+ await fs.rename(tempPath, resolvedPath);
108
+ await fsyncDirectory(dir, fs);
109
+ } catch (err) {
110
+ if (handle !== null) {
111
+ await handle.close().catch(() => void 0);
112
+ }
113
+ await fs.unlink(tempPath).catch(() => void 0);
114
+ throw err;
115
+ }
72
116
  },
73
117
  async load(key) {
74
118
  const resolvedPath = await resolveAndGuard(baseDir, key);
@@ -1,4 +1,4 @@
1
- import { P as PersistenceAdapter } from '../adapters-BbRkoiu9.js';
1
+ import { b as PersistenceAdapter } from '../adapters-Bo2JQg8b.js';
2
2
 
3
3
  interface IndexedDBPersistenceConfig {
4
4
  dbName?: string;
@@ -1,4 +1,4 @@
1
- import { NarsilError, ErrorCodes } from '../chunk-R2C2EQGO.mjs';
1
+ import { NarsilError, ErrorCodes } from '../chunk-ALB35PRQ.mjs';
2
2
 
3
3
  // src/persistence/indexeddb.ts
4
4
  var DEFAULT_DB_NAME = "narsil";
@@ -1,4 +1,4 @@
1
- import { P as PersistenceAdapter } from '../adapters-BbRkoiu9.js';
1
+ import { b as PersistenceAdapter } from '../adapters-Bo2JQg8b.js';
2
2
 
3
3
  declare function createMemoryPersistence(): PersistenceAdapter;
4
4
 
@@ -3,6 +3,7 @@ interface PersistenceAdapter {
3
3
  load(key: string): Promise<Uint8Array | null>;
4
4
  delete(key: string): Promise<void>;
5
5
  list(prefix: string): Promise<string[]>;
6
+ readonly directory?: string;
6
7
  }
7
8
  interface InvalidationAdapter {
8
9
  publish(event: InvalidationEvent): Promise<void>;
@@ -33,4 +34,4 @@ interface EmbeddingAdapter {
33
34
  shutdown?(): Promise<void>;
34
35
  }
35
36
 
36
- export type { EmbeddingAdapter as E, InvalidationAdapter as I, PersistenceAdapter as P, InvalidationEvent as a, PartitionStatistics as b };
37
+ export type { EmbeddingAdapter as E, InvalidationAdapter as I, PartitionStatistics as P, InvalidationEvent as a, PersistenceAdapter as b };
@@ -0,0 +1,98 @@
1
+ // src/errors.ts
2
+ var ErrorCodes = {
3
+ SCHEMA_INVALID_TYPE: "SCHEMA_INVALID_TYPE",
4
+ SCHEMA_MISSING_FIELD: "SCHEMA_MISSING_FIELD",
5
+ SCHEMA_DEPTH_EXCEEDED: "SCHEMA_DEPTH_EXCEEDED",
6
+ SCHEMA_INVALID_VECTOR_DIMENSION: "SCHEMA_INVALID_VECTOR_DIMENSION",
7
+ SCHEMA_INVALID_GEOPOINT: "SCHEMA_INVALID_GEOPOINT",
8
+ DOC_NOT_FOUND: "DOC_NOT_FOUND",
9
+ DOC_ALREADY_EXISTS: "DOC_ALREADY_EXISTS",
10
+ DOC_VALIDATION_FAILED: "DOC_VALIDATION_FAILED",
11
+ INDEX_NOT_FOUND: "INDEX_NOT_FOUND",
12
+ INDEX_ALREADY_EXISTS: "INDEX_ALREADY_EXISTS",
13
+ PARTITION_CORRUPTED: "PARTITION_CORRUPTED",
14
+ PARTITION_REBALANCING_BACKPRESSURE: "PARTITION_REBALANCING_BACKPRESSURE",
15
+ WORKER_CRASHED: "WORKER_CRASHED",
16
+ WORKER_BUSY: "WORKER_BUSY",
17
+ WORKER_TIMEOUT: "WORKER_TIMEOUT",
18
+ PERSISTENCE_SAVE_FAILED: "PERSISTENCE_SAVE_FAILED",
19
+ PERSISTENCE_LOAD_FAILED: "PERSISTENCE_LOAD_FAILED",
20
+ PERSISTENCE_DELETE_FAILED: "PERSISTENCE_DELETE_FAILED",
21
+ PERSISTENCE_CRC_MISMATCH: "PERSISTENCE_CRC_MISMATCH",
22
+ PERSISTENCE_WAL_CORRUPT: "PERSISTENCE_WAL_CORRUPT",
23
+ PERSISTENCE_FSYNC_FAILED: "PERSISTENCE_FSYNC_FAILED",
24
+ SEARCH_INVALID_FIELD: "SEARCH_INVALID_FIELD",
25
+ SEARCH_INVALID_VECTOR_SIZE: "SEARCH_INVALID_VECTOR_SIZE",
26
+ VECTOR_DIMENSION_MISMATCH: "VECTOR_DIMENSION_MISMATCH",
27
+ SEARCH_INVALID_FILTER: "SEARCH_INVALID_FILTER",
28
+ SEARCH_INVALID_MODE: "SEARCH_INVALID_MODE",
29
+ SEARCH_INVALID_CURSOR: "SEARCH_INVALID_CURSOR",
30
+ LANGUAGE_NOT_SUPPORTED: "LANGUAGE_NOT_SUPPORTED",
31
+ ENVELOPE_VERSION_MISMATCH: "ENVELOPE_VERSION_MISMATCH",
32
+ ENVELOPE_INVALID_MAGIC: "ENVELOPE_INVALID_MAGIC",
33
+ PARTITION_CAPACITY_EXCEEDED: "PARTITION_CAPACITY_EXCEEDED",
34
+ EMBEDDING_FAILED: "EMBEDDING_FAILED",
35
+ EMBEDDING_DIMENSION_MISMATCH: "EMBEDDING_DIMENSION_MISMATCH",
36
+ EMBEDDING_NO_SOURCE: "EMBEDDING_NO_SOURCE",
37
+ EMBEDDING_CONFIG_INVALID: "EMBEDDING_CONFIG_INVALID",
38
+ DOC_MISSING_REQUIRED_FIELD: "DOC_MISSING_REQUIRED_FIELD",
39
+ CONFIG_INVALID: "CONFIG_INVALID",
40
+ QUERY_ROUTING_FAILED: "QUERY_ROUTING_FAILED",
41
+ QUERY_PARTIAL_FAILURE: "QUERY_PARTIAL_FAILURE",
42
+ QUERY_NODE_TIMEOUT: "QUERY_NODE_TIMEOUT",
43
+ QUERY_NO_ACTIVE_REPLICA: "QUERY_NO_ACTIVE_REPLICA",
44
+ ALLOCATION_NO_DATA_NODES: "ALLOCATION_NO_DATA_NODES",
45
+ ALLOCATION_INVALID_CONFIG: "ALLOCATION_INVALID_CONFIG",
46
+ ALLOCATION_FAILED: "ALLOCATION_FAILED",
47
+ CONTROLLER_LEASE_LOST: "CONTROLLER_LEASE_LOST",
48
+ CONTROLLER_NOT_ACTIVE: "CONTROLLER_NOT_ACTIVE",
49
+ CONTROLLER_METADATA_INVALID: "CONTROLLER_METADATA_INVALID",
50
+ NODE_BOOTSTRAP_FAILED: "NODE_BOOTSTRAP_FAILED",
51
+ NODE_ALREADY_JOINED: "NODE_ALREADY_JOINED",
52
+ NODE_NOT_JOINED: "NODE_NOT_JOINED",
53
+ COORDINATOR_DEPENDENCY_MISSING: "COORDINATOR_DEPENDENCY_MISSING",
54
+ REPLICATION_ENTRY_INVALID: "REPLICATION_ENTRY_INVALID",
55
+ REPLICATION_INSYNC_REMOVAL_FAILED: "REPLICATION_INSYNC_REMOVAL_FAILED",
56
+ REPLICATION_ROLLBACK_FAILED: "REPLICATION_ROLLBACK_FAILED",
57
+ SNAPSHOT_SYNC_UNAUTHORIZED: "SNAPSHOT_SYNC_UNAUTHORIZED",
58
+ SNAPSHOT_SYNC_REQUEST_INVALID: "SNAPSHOT_SYNC_REQUEST_INVALID",
59
+ SNAPSHOT_SYNC_INDEX_NOT_FOUND: "SNAPSHOT_SYNC_INDEX_NOT_FOUND",
60
+ SNAPSHOT_SYNC_TOO_LARGE: "SNAPSHOT_SYNC_TOO_LARGE",
61
+ SNAPSHOT_SYNC_CAPACITY_EXHAUSTED: "SNAPSHOT_SYNC_CAPACITY_EXHAUSTED",
62
+ SNAPSHOT_SYNC_SNAPSHOT_FAILED: "SNAPSHOT_SYNC_SNAPSHOT_FAILED",
63
+ SNAPSHOT_SYNC_DECODE_FAILED: "SNAPSHOT_SYNC_DECODE_FAILED",
64
+ SNAPSHOT_SYNC_FRAME_INVALID: "SNAPSHOT_SYNC_FRAME_INVALID",
65
+ SNAPSHOT_SYNC_HEADER_INVALID: "SNAPSHOT_SYNC_HEADER_INVALID",
66
+ SNAPSHOT_SYNC_HEADER_MISMATCH: "SNAPSHOT_SYNC_HEADER_MISMATCH",
67
+ SNAPSHOT_SYNC_CHUNK_OUT_OF_ORDER: "SNAPSHOT_SYNC_CHUNK_OUT_OF_ORDER",
68
+ SNAPSHOT_SYNC_CHUNK_OVERFLOW: "SNAPSHOT_SYNC_CHUNK_OVERFLOW",
69
+ SNAPSHOT_SYNC_CHUNK_SIZE_EXCEEDED: "SNAPSHOT_SYNC_CHUNK_SIZE_EXCEEDED",
70
+ SNAPSHOT_SYNC_CHUNK_MISSING: "SNAPSHOT_SYNC_CHUNK_MISSING",
71
+ SNAPSHOT_SYNC_END_MISSING: "SNAPSHOT_SYNC_END_MISSING",
72
+ SNAPSHOT_SYNC_CHECKSUM_MISMATCH: "SNAPSHOT_SYNC_CHECKSUM_MISMATCH",
73
+ SNAPSHOT_SYNC_PRIMARY_ERROR: "SNAPSHOT_SYNC_PRIMARY_ERROR",
74
+ SNAPSHOT_SYNC_NO_TARGETS: "SNAPSHOT_SYNC_NO_TARGETS",
75
+ SNAPSHOT_SYNC_TRANSPORT_FAILED: "SNAPSHOT_SYNC_TRANSPORT_FAILED",
76
+ SNAPSHOT_SYNC_SCHEMA_UNAVAILABLE: "SNAPSHOT_SYNC_SCHEMA_UNAVAILABLE",
77
+ SNAPSHOT_SYNC_RESTORE_FAILED: "SNAPSHOT_SYNC_RESTORE_FAILED",
78
+ SNAPSHOT_SYNC_RESTORE_CLEANUP_FAILED: "SNAPSHOT_SYNC_RESTORE_CLEANUP_FAILED",
79
+ SNAPSHOT_SYNC_TIMEOUT: "SNAPSHOT_SYNC_TIMEOUT",
80
+ SNAPSHOT_SYNC_ALLOCATION_UNAVAILABLE: "SNAPSHOT_SYNC_ALLOCATION_UNAVAILABLE",
81
+ SNAPSHOT_SYNC_NOT_ASSIGNED: "SNAPSHOT_SYNC_NOT_ASSIGNED",
82
+ SNAPSHOT_SYNC_ABORTED: "SNAPSHOT_SYNC_ABORTED"
83
+ };
84
+ var NarsilError = class extends Error {
85
+ code;
86
+ details;
87
+ constructor(code, message, details) {
88
+ super(message);
89
+ this.name = "NarsilError";
90
+ this.code = code;
91
+ this.details = details ?? {};
92
+ }
93
+ };
94
+ function createNarsilError(code, message, details) {
95
+ return new NarsilError(code, message, details);
96
+ }
97
+
98
+ export { ErrorCodes, NarsilError, createNarsilError };