@delali/narsil 0.3.1-next.69 → 0.3.1-next.71
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.
- package/dist/{capabilities-B1wz2Zl0.d.ts → capabilities-Dt-7B4Wz.d.ts} +2 -2
- package/dist/{chunk-DD5X23E6.mjs → chunk-2STVUTNA.mjs} +1 -1
- package/dist/chunk-3JGWULDF.mjs +256 -0
- package/dist/{chunk-6TGZG2TV.mjs → chunk-653BNMAF.mjs} +190 -58
- package/dist/{chunk-YA52AC2V.mjs → chunk-FVLQ63B7.mjs} +203 -9
- package/dist/{chunk-5JLSTECC.mjs → chunk-GIVAGD3Q.mjs} +1 -1
- package/dist/{chunk-AV4IJKD2.mjs → chunk-HWQLTLNG.mjs} +18 -1
- package/dist/{chunk-6IT3MH5M.mjs → chunk-IOR2K26O.mjs} +178 -238
- package/dist/{chunk-4VU5TWCR.mjs → chunk-LMO5TJUS.mjs} +40 -35
- package/dist/{chunk-BEWOA4VV.mjs → chunk-M76V3OGJ.mjs} +508 -401
- package/dist/{chunk-YMZCMH5M.mjs → chunk-OI42GWLR.mjs} +17 -1
- package/dist/{chunk-2BDG2IWP.mjs → chunk-P4DSQ6M4.mjs} +16 -6
- package/dist/{chunk-THYRHHO2.mjs → chunk-YJDQ7NLA.mjs} +1 -1
- package/dist/{client-xVrOCYTW.d.ts → client-COek5GXK.d.ts} +3 -3
- package/dist/client.d.ts +8 -8
- package/dist/{config-CEeSV_Xo.d.ts → config-Dfanyqqt.d.ts} +2 -2
- package/dist/{config-CSvCVtB7.d.ts → config-rBpbgTw8.d.ts} +2 -2
- package/dist/direct-executor-GYJEKNV5.mjs +12 -0
- package/dist/distribution/coordinator/etcd.d.ts +2 -2
- package/dist/distribution/coordinator/etcd.mjs +1 -1
- package/dist/distribution/coordinator/in-memory.d.ts +2 -2
- package/dist/distribution/coordinator/in-memory.mjs +1 -1
- package/dist/distribution.d.ts +8 -8
- package/dist/distribution.mjs +109 -69
- package/dist/{engine-77ErLy8P.d.ts → engine-igk0aMpQ.d.ts} +109 -60
- package/dist/index.browser.mjs +1167 -749
- package/dist/index.d.ts +7 -7
- package/dist/index.mjs +10 -10
- package/dist/invalidation/filesystem.mjs +1 -1
- package/dist/{memory-CKF-9WLP.d.ts → memory-C7UMCMH3.d.ts} +35 -17
- package/dist/persistence/durability/checkpoint-worker.d.ts +2 -1
- package/dist/persistence/durability/checkpoint-worker.mjs +10 -10
- package/dist/react.d.ts +277 -182
- package/dist/react.mjs +189 -45
- package/dist/{schema-d5Afu03A.d.ts → schema-Bgzr4g7b.d.ts} +62 -10
- package/dist/server.d.ts +10 -10
- package/dist/server.mjs +11 -7
- package/dist/{tasks-BEiNxDRs.d.ts → tasks-BZt_zes6.d.ts} +3 -1
- package/dist/{thread-FLP45EUD.mjs → thread-JEVAYETR.mjs} +6 -6
- package/dist/{types-DAK7mnUZ.d.ts → types-gOUqhs2F.d.ts} +1 -1
- package/dist/vector/search-worker.d.ts +1 -1
- package/dist/vector/search-worker.mjs +2 -2
- package/dist/workers/entry.mjs +3 -3
- package/package.json +7 -7
- package/dist/chunk-VTPLKNWI.mjs +0 -135
- package/dist/direct-executor-3ZYXSGFX.mjs +0 -12
package/dist/react.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createContext, useState,
|
|
1
|
+
import { createContext, useState, createElement, useRef, useEffectEvent, useEffect, useCallback, useMemo, useContext, useSyncExternalStore } from 'react';
|
|
2
2
|
|
|
3
3
|
// src/errors.ts
|
|
4
4
|
var NARSIL_ERROR_MARKER = /* @__PURE__ */ Symbol.for("@delali/narsil.NarsilError");
|
|
@@ -147,8 +147,53 @@ function isNarsilError(value) {
|
|
|
147
147
|
return typeof value === "object" && value !== null && NARSIL_ERROR_MARKER in value;
|
|
148
148
|
}
|
|
149
149
|
|
|
150
|
+
// src/react/reader.ts
|
|
151
|
+
function plainNumbersIn(value) {
|
|
152
|
+
if (value === null || typeof value !== "object") return value;
|
|
153
|
+
if (ArrayBuffer.isView(value)) {
|
|
154
|
+
return value instanceof DataView ? value : Array.from(value);
|
|
155
|
+
}
|
|
156
|
+
if (Array.isArray(value)) {
|
|
157
|
+
let copy2 = null;
|
|
158
|
+
for (let at = 0; at < value.length; at++) {
|
|
159
|
+
const converted = plainNumbersIn(value[at]);
|
|
160
|
+
if (converted === value[at]) continue;
|
|
161
|
+
copy2 ??= value.slice();
|
|
162
|
+
copy2[at] = converted;
|
|
163
|
+
}
|
|
164
|
+
return copy2 ?? value;
|
|
165
|
+
}
|
|
166
|
+
let copy = null;
|
|
167
|
+
for (const [key, held] of Object.entries(value)) {
|
|
168
|
+
const converted = plainNumbersIn(held);
|
|
169
|
+
if (converted === held) continue;
|
|
170
|
+
copy ??= { ...value };
|
|
171
|
+
copy[key] = converted;
|
|
172
|
+
}
|
|
173
|
+
return copy ?? value;
|
|
174
|
+
}
|
|
175
|
+
function withPlainNumbers(answer) {
|
|
176
|
+
return answer.then((value) => plainNumbersIn(value));
|
|
177
|
+
}
|
|
178
|
+
function engineReader(engine) {
|
|
179
|
+
return {
|
|
180
|
+
query(indexName, params) {
|
|
181
|
+
return withPlainNumbers(engine.query(indexName, params));
|
|
182
|
+
},
|
|
183
|
+
preflight: (indexName, params) => engine.preflight(indexName, params),
|
|
184
|
+
suggest: (indexName, params) => engine.suggest(indexName, params),
|
|
185
|
+
get: (indexName, docId) => withPlainNumbers(engine.get(indexName, docId)),
|
|
186
|
+
listDocuments(indexName, params) {
|
|
187
|
+
return withPlainNumbers(engine.listDocuments(indexName, params));
|
|
188
|
+
},
|
|
189
|
+
listIndexes: async () => engine.listIndexes(),
|
|
190
|
+
getStats: async (indexName) => engine.getStats(indexName)
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
|
|
150
194
|
// src/react/constants.ts
|
|
151
195
|
var DEFAULT_KEEP_ALIVE_MS = 2e3;
|
|
196
|
+
var DEFAULT_REFRESH_AFTER_WRITE_MS = 200;
|
|
152
197
|
var DEFAULT_TASK_POLL_INTERVAL_MS = 250;
|
|
153
198
|
var ERROR_RETRY_INTERVAL_MS = 5e3;
|
|
154
199
|
var MAX_QUERY_KEY_DEPTH = 32;
|
|
@@ -173,10 +218,13 @@ var IDLE_SNAPSHOT = Object.freeze({
|
|
|
173
218
|
isLoading: false,
|
|
174
219
|
isFetching: false
|
|
175
220
|
});
|
|
176
|
-
|
|
221
|
+
var ANY_INDEX = /* @__PURE__ */ Symbol("any index");
|
|
222
|
+
var NO_INDEX = /* @__PURE__ */ Symbol("no index");
|
|
223
|
+
function createResourceStore(keepAliveMs = DEFAULT_KEEP_ALIVE_MS, refreshAfterWriteMs = DEFAULT_REFRESH_AFTER_WRITE_MS) {
|
|
177
224
|
const entries = /* @__PURE__ */ new Map();
|
|
178
225
|
let holders = 0;
|
|
179
226
|
let closing = null;
|
|
227
|
+
const staleRefreshes = /* @__PURE__ */ new Map();
|
|
180
228
|
function publish(entry, next) {
|
|
181
229
|
entry.snapshot = next;
|
|
182
230
|
for (const listener of entry.listeners) listener();
|
|
@@ -185,6 +233,7 @@ function createResourceStore(keepAliveMs = DEFAULT_KEEP_ALIVE_MS) {
|
|
|
185
233
|
if (entry.controller !== null) return;
|
|
186
234
|
const controller = new AbortController();
|
|
187
235
|
entry.controller = controller;
|
|
236
|
+
entry.stale = false;
|
|
188
237
|
entry.version++;
|
|
189
238
|
const version = entry.version;
|
|
190
239
|
if (!entry.snapshot.isFetching) publish(entry, { ...entry.snapshot, isFetching: true });
|
|
@@ -209,9 +258,32 @@ function createResourceStore(keepAliveMs = DEFAULT_KEEP_ALIVE_MS) {
|
|
|
209
258
|
);
|
|
210
259
|
}
|
|
211
260
|
function disposeAll() {
|
|
261
|
+
for (const timer of staleRefreshes.values()) clearTimeout(timer);
|
|
262
|
+
staleRefreshes.clear();
|
|
212
263
|
for (const [key, entry] of [...entries]) drop(key, entry);
|
|
213
264
|
entries.clear();
|
|
214
265
|
}
|
|
266
|
+
function refreshStale(scope) {
|
|
267
|
+
staleRefreshes.delete(scope);
|
|
268
|
+
for (const [key, entry] of entries) {
|
|
269
|
+
if (entry.writeScope === scope && entry.stale && entry.listeners.size > 0) load(key, entry);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
function scheduleRefresh(scope) {
|
|
273
|
+
const pending = staleRefreshes.get(scope);
|
|
274
|
+
if (pending !== void 0) clearTimeout(pending);
|
|
275
|
+
staleRefreshes.set(
|
|
276
|
+
scope,
|
|
277
|
+
setTimeout(() => refreshStale(scope), refreshAfterWriteMs)
|
|
278
|
+
);
|
|
279
|
+
}
|
|
280
|
+
function markStale(entry) {
|
|
281
|
+
entry.stale = true;
|
|
282
|
+
if (entry.controller === null) return;
|
|
283
|
+
entry.controller.abort();
|
|
284
|
+
entry.controller = null;
|
|
285
|
+
entry.version++;
|
|
286
|
+
}
|
|
215
287
|
function drop(key, entry) {
|
|
216
288
|
if (entries.get(key) === entry) entries.delete(key);
|
|
217
289
|
if (entry.disposal !== null) clearTimeout(entry.disposal);
|
|
@@ -220,7 +292,7 @@ function createResourceStore(keepAliveMs = DEFAULT_KEEP_ALIVE_MS) {
|
|
|
220
292
|
entry.controller = null;
|
|
221
293
|
}
|
|
222
294
|
return {
|
|
223
|
-
subscribe(key, loader, onChange) {
|
|
295
|
+
subscribe(key, loader, onChange, writeScope) {
|
|
224
296
|
let entry = entries.get(key);
|
|
225
297
|
if (entry === void 0) {
|
|
226
298
|
entry = {
|
|
@@ -229,7 +301,9 @@ function createResourceStore(keepAliveMs = DEFAULT_KEEP_ALIVE_MS) {
|
|
|
229
301
|
loader,
|
|
230
302
|
controller: null,
|
|
231
303
|
version: 0,
|
|
232
|
-
disposal: null
|
|
304
|
+
disposal: null,
|
|
305
|
+
writeScope,
|
|
306
|
+
stale: false
|
|
233
307
|
};
|
|
234
308
|
entries.set(key, entry);
|
|
235
309
|
} else {
|
|
@@ -241,7 +315,7 @@ function createResourceStore(keepAliveMs = DEFAULT_KEEP_ALIVE_MS) {
|
|
|
241
315
|
}
|
|
242
316
|
const held = entry;
|
|
243
317
|
held.listeners.add(onChange);
|
|
244
|
-
const retryable = held.snapshot.isLoading || held.snapshot.error !== void 0;
|
|
318
|
+
const retryable = held.stale || held.snapshot.isLoading || held.snapshot.error !== void 0;
|
|
245
319
|
if (retryable && held.controller === null) load(key, held);
|
|
246
320
|
return () => {
|
|
247
321
|
held.listeners.delete(onChange);
|
|
@@ -259,6 +333,15 @@ function createResourceStore(keepAliveMs = DEFAULT_KEEP_ALIVE_MS) {
|
|
|
259
333
|
const entry = entries.get(key);
|
|
260
334
|
if (entry !== void 0) load(key, entry);
|
|
261
335
|
},
|
|
336
|
+
invalidate(indexName) {
|
|
337
|
+
const marked = /* @__PURE__ */ new Set();
|
|
338
|
+
for (const entry of entries.values()) {
|
|
339
|
+
if (entry.writeScope !== ANY_INDEX && entry.writeScope !== indexName) continue;
|
|
340
|
+
markStale(entry);
|
|
341
|
+
marked.add(entry.writeScope);
|
|
342
|
+
}
|
|
343
|
+
for (const scope of marked) scheduleRefresh(scope);
|
|
344
|
+
},
|
|
262
345
|
retain() {
|
|
263
346
|
holders++;
|
|
264
347
|
if (closing !== null) {
|
|
@@ -283,30 +366,72 @@ function createResourceStore(keepAliveMs = DEFAULT_KEEP_ALIVE_MS) {
|
|
|
283
366
|
|
|
284
367
|
// src/react/context.ts
|
|
285
368
|
var NarsilContext = createContext(null);
|
|
286
|
-
function
|
|
287
|
-
|
|
369
|
+
function buildContextValue(props) {
|
|
370
|
+
const { client, engine, keepAliveMs, refreshAfterWriteMs } = props;
|
|
371
|
+
const shared = { store: createResourceStore(keepAliveMs, refreshAfterWriteMs), keepAliveMs, refreshAfterWriteMs };
|
|
372
|
+
if (client !== void 0 && engine === void 0) return { ...shared, reader: client, client, engine: null };
|
|
373
|
+
if (engine !== void 0 && client === void 0) {
|
|
374
|
+
return { ...shared, reader: engineReader(engine), client: null, engine };
|
|
375
|
+
}
|
|
376
|
+
throw new NarsilError(
|
|
377
|
+
ErrorCodes.CONFIG_INVALID,
|
|
378
|
+
"A NarsilProvider requires exactly one of client and engine, but its props set both or neither"
|
|
379
|
+
);
|
|
380
|
+
}
|
|
381
|
+
function providerPropsChanged(value, props) {
|
|
382
|
+
return value.client !== (props.client ?? null) || value.engine !== (props.engine ?? null) || value.keepAliveMs !== props.keepAliveMs || value.refreshAfterWriteMs !== props.refreshAfterWriteMs;
|
|
383
|
+
}
|
|
384
|
+
function useStoreRetention(store) {
|
|
385
|
+
useEffect(() => store.retain(), [store]);
|
|
386
|
+
}
|
|
387
|
+
function useRefreshAfterWrites(engine, store) {
|
|
388
|
+
useEffect(() => {
|
|
389
|
+
if (engine === null) return;
|
|
390
|
+
const onWrite = (payload) => {
|
|
391
|
+
store.invalidate(payload.indexName);
|
|
392
|
+
};
|
|
393
|
+
engine.on("write", onWrite);
|
|
394
|
+
return () => {
|
|
395
|
+
engine.off("write", onWrite);
|
|
396
|
+
};
|
|
397
|
+
}, [engine, store]);
|
|
288
398
|
}
|
|
289
399
|
function NarsilProvider(props) {
|
|
290
|
-
const
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
setValue(build(client, keepAliveMs));
|
|
400
|
+
const [value, setValue] = useState(() => buildContextValue(props));
|
|
401
|
+
if (providerPropsChanged(value, props)) {
|
|
402
|
+
setValue(buildContextValue(props));
|
|
294
403
|
}
|
|
295
|
-
|
|
296
|
-
|
|
404
|
+
useStoreRetention(value.store);
|
|
405
|
+
useRefreshAfterWrites(value.engine, value.store);
|
|
406
|
+
return createElement(NarsilContext.Provider, { value }, props.children);
|
|
297
407
|
}
|
|
298
408
|
function useNarsilContext() {
|
|
299
409
|
const value = useContext(NarsilContext);
|
|
300
410
|
if (value === null) {
|
|
301
411
|
throw new NarsilError(
|
|
302
412
|
ErrorCodes.CONFIG_INVALID,
|
|
303
|
-
"A Narsil hook
|
|
413
|
+
"A Narsil hook was called outside a NarsilProvider, so no client or engine is available to it"
|
|
304
414
|
);
|
|
305
415
|
}
|
|
306
416
|
return value;
|
|
307
417
|
}
|
|
418
|
+
function useServerClient(hookName) {
|
|
419
|
+
const { client } = useNarsilContext();
|
|
420
|
+
if (client !== null) return client;
|
|
421
|
+
throw new NarsilError(
|
|
422
|
+
ErrorCodes.CONFIG_INVALID,
|
|
423
|
+
`${hookName} works only under a client of a server, because only a server handles tasks and imports, while the NarsilProvider above it holds an engine`,
|
|
424
|
+
{ hook: hookName }
|
|
425
|
+
);
|
|
426
|
+
}
|
|
308
427
|
function useNarsilClient() {
|
|
309
|
-
|
|
428
|
+
const { client } = useNarsilContext();
|
|
429
|
+
if (client !== null) return client;
|
|
430
|
+
throw new NarsilError(
|
|
431
|
+
ErrorCodes.CONFIG_INVALID,
|
|
432
|
+
"useNarsilClient returns a client, while the NarsilProvider above it holds an engine, so import that engine directly",
|
|
433
|
+
{ hook: "useNarsilClient" }
|
|
434
|
+
);
|
|
310
435
|
}
|
|
311
436
|
|
|
312
437
|
// src/react/key.ts
|
|
@@ -457,8 +582,8 @@ function useKey(parts) {
|
|
|
457
582
|
cached.current = { parts, key };
|
|
458
583
|
return key;
|
|
459
584
|
}
|
|
460
|
-
function useRead(parts, run, options) {
|
|
461
|
-
const {
|
|
585
|
+
function useRead(source, parts, run, options, writeScope) {
|
|
586
|
+
const { store } = useNarsilContext();
|
|
462
587
|
const enabled = options?.enabled ?? true;
|
|
463
588
|
const headers = options?.headers;
|
|
464
589
|
const timeoutMs = options?.timeoutMs;
|
|
@@ -472,11 +597,11 @@ function useRead(parts, run, options) {
|
|
|
472
597
|
if (!enabled) return NO_SUBSCRIPTION;
|
|
473
598
|
const loader = (signal) => {
|
|
474
599
|
const held = call.current;
|
|
475
|
-
return held.run(
|
|
600
|
+
return held.run(source, { ...held.request, signal });
|
|
476
601
|
};
|
|
477
|
-
return store.subscribe(key, loader, onChange);
|
|
602
|
+
return store.subscribe(key, loader, onChange, writeScope);
|
|
478
603
|
},
|
|
479
|
-
[enabled, store,
|
|
604
|
+
[enabled, store, source, key, writeScope]
|
|
480
605
|
);
|
|
481
606
|
const readSnapshot = useCallback(
|
|
482
607
|
() => enabled ? store.snapshot(key) : IDLE_SNAPSHOT,
|
|
@@ -508,21 +633,28 @@ function useRead(parts, run, options) {
|
|
|
508
633
|
[data, snapshot, refresh]
|
|
509
634
|
);
|
|
510
635
|
}
|
|
636
|
+
function useProviderRead(parts, run, options, writeScope) {
|
|
637
|
+
const { reader } = useNarsilContext();
|
|
638
|
+
return useRead(reader, parts, run, options, writeScope);
|
|
639
|
+
}
|
|
511
640
|
|
|
512
641
|
// src/react/documents.ts
|
|
513
642
|
function useDocument(indexName, docId, options) {
|
|
514
643
|
const id = docId ?? "";
|
|
515
644
|
const enabled = (options?.enabled ?? true) && id.length > 0;
|
|
516
|
-
return
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
645
|
+
return useProviderRead(
|
|
646
|
+
["get", indexName, id],
|
|
647
|
+
(reader, request) => reader.get(indexName, id, request),
|
|
648
|
+
{ ...options, enabled },
|
|
649
|
+
indexName
|
|
650
|
+
);
|
|
520
651
|
}
|
|
521
652
|
function useDocuments(indexName, params, options) {
|
|
522
|
-
return
|
|
653
|
+
return useProviderRead(
|
|
523
654
|
["listDocuments", indexName, params],
|
|
524
|
-
(
|
|
525
|
-
options
|
|
655
|
+
(reader, request) => reader.listDocuments(indexName, params, request),
|
|
656
|
+
options,
|
|
657
|
+
indexName
|
|
526
658
|
);
|
|
527
659
|
}
|
|
528
660
|
|
|
@@ -544,7 +676,7 @@ function isTerminalTask(record) {
|
|
|
544
676
|
// src/react/import.ts
|
|
545
677
|
var NOTHING = { task: void 0, error: void 0, starting: false };
|
|
546
678
|
function useImport(indexName, options) {
|
|
547
|
-
const client =
|
|
679
|
+
const client = useServerClient("useImport");
|
|
548
680
|
const [progress, setProgress] = useState(NOTHING);
|
|
549
681
|
const polling = useRef(null);
|
|
550
682
|
const sending = useRef(null);
|
|
@@ -652,51 +784,63 @@ function useImport(indexName, options) {
|
|
|
652
784
|
|
|
653
785
|
// src/react/indexes.ts
|
|
654
786
|
function useIndexes(options) {
|
|
655
|
-
return
|
|
787
|
+
return useProviderRead(["listIndexes"], (reader, request) => reader.listIndexes(request), options, ANY_INDEX);
|
|
656
788
|
}
|
|
657
789
|
function useStats(indexName, options) {
|
|
658
|
-
return
|
|
790
|
+
return useProviderRead(
|
|
791
|
+
["getStats", indexName],
|
|
792
|
+
(reader, request) => reader.getStats(indexName, request),
|
|
793
|
+
options,
|
|
794
|
+
indexName
|
|
795
|
+
);
|
|
659
796
|
}
|
|
660
797
|
|
|
661
798
|
// src/react/search.ts
|
|
662
799
|
function useQuery(indexName, params, options) {
|
|
663
|
-
return
|
|
800
|
+
return useProviderRead(
|
|
664
801
|
["query", indexName, params],
|
|
665
|
-
(
|
|
666
|
-
options
|
|
802
|
+
(reader, request) => reader.query(indexName, params, request),
|
|
803
|
+
options,
|
|
804
|
+
indexName
|
|
667
805
|
);
|
|
668
806
|
}
|
|
669
807
|
function usePreflight(indexName, params, options) {
|
|
670
|
-
return
|
|
808
|
+
return useProviderRead(
|
|
671
809
|
["preflight", indexName, params],
|
|
672
|
-
(
|
|
673
|
-
options
|
|
810
|
+
(reader, request) => reader.preflight(indexName, params, request),
|
|
811
|
+
options,
|
|
812
|
+
indexName
|
|
674
813
|
);
|
|
675
814
|
}
|
|
676
815
|
function useSuggest(indexName, params, options) {
|
|
677
|
-
return
|
|
816
|
+
return useProviderRead(
|
|
678
817
|
["suggest", indexName, params],
|
|
679
|
-
(
|
|
680
|
-
options
|
|
818
|
+
(reader, request) => reader.suggest(indexName, params, request),
|
|
819
|
+
options,
|
|
820
|
+
indexName
|
|
681
821
|
);
|
|
682
822
|
}
|
|
683
823
|
|
|
684
824
|
// src/react/tasks.ts
|
|
685
825
|
function useTask(taskId, options) {
|
|
826
|
+
const client = useServerClient("useTask");
|
|
686
827
|
const id = taskId ?? "";
|
|
687
828
|
const enabled = (options?.enabled ?? true) && id.length > 0;
|
|
688
|
-
const state = useRead(
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
829
|
+
const state = useRead(
|
|
830
|
+
client,
|
|
831
|
+
["getTask", id],
|
|
832
|
+
(server, request) => server.getTask(id, request),
|
|
833
|
+
{ ...options, enabled, refreshIntervalMs: 0 },
|
|
834
|
+
NO_INDEX
|
|
835
|
+
);
|
|
693
836
|
const running = state.data !== null && !isTerminalTask(state.data);
|
|
694
837
|
const interval = pollInterval(options?.pollIntervalMs ?? DEFAULT_TASK_POLL_INTERVAL_MS, state.error !== void 0);
|
|
695
838
|
usePolling(state.refresh, interval, enabled && running);
|
|
696
839
|
return state;
|
|
697
840
|
}
|
|
698
841
|
function useTasks(query, options) {
|
|
699
|
-
|
|
842
|
+
const client = useServerClient("useTasks");
|
|
843
|
+
return useRead(client, ["listTasks", query], (server, request) => server.listTasks(query, request), options, NO_INDEX);
|
|
700
844
|
}
|
|
701
845
|
|
|
702
846
|
export { ClientErrorCodes, ErrorCodes, NarsilError, NarsilProvider, ServerErrorCodes, isNarsilError, useDocument, useDocuments, useImport, useIndexes, useNarsilClient, usePreflight, useQuery, useStats, useSuggest, useTask, useTasks };
|
|
@@ -13,20 +13,63 @@ type AnyDocument = Record<string, unknown> & {
|
|
|
13
13
|
id?: string;
|
|
14
14
|
};
|
|
15
15
|
/**
|
|
16
|
-
*
|
|
16
|
+
* Each of these options can follow the base type of a `string` or `string[]`
|
|
17
|
+
* field after a colon, as in `string:sortable:pattern`.
|
|
17
18
|
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
19
|
+
* The engine can sort by a field whose type includes `sortable`. On a single
|
|
20
|
+
* `string` field with that option, the engine can also test a text range with
|
|
21
|
+
* `gt`, `gte`, `lt`, `lte`, or `between`. The engine raises
|
|
22
|
+
* `DOC_VALIDATION_FAILED` for a value longer than
|
|
23
|
+
* {@link IndexConfig.patternValueLimit} in a field whose type includes
|
|
24
|
+
* `pattern`. A later release will add pattern search and partial-word search,
|
|
25
|
+
* which will test the fields whose types include `pattern` and `partial`
|
|
26
|
+
* respectively.
|
|
22
27
|
*
|
|
23
|
-
*
|
|
24
|
-
|
|
25
|
-
|
|
28
|
+
* @public
|
|
29
|
+
*/
|
|
30
|
+
type TextFieldOption = 'sortable' | 'pattern' | 'partial';
|
|
31
|
+
/**
|
|
32
|
+
* This union contains every string of options that can follow a base type,
|
|
33
|
+
* with each option after a colon. The options can come in any order, although
|
|
34
|
+
* each one can appear only once.
|
|
26
35
|
*
|
|
27
36
|
* @public
|
|
28
37
|
*/
|
|
29
|
-
type
|
|
38
|
+
type FieldOptionChain<Remaining extends string> = {
|
|
39
|
+
[Option in Remaining]: `:${Option}` | `:${Option}${FieldOptionChain<Exclude<Remaining, Option>>}`;
|
|
40
|
+
}[Remaining];
|
|
41
|
+
/**
|
|
42
|
+
* The engine indexes each field of a schema according to the field's type,
|
|
43
|
+
* which is one of these.
|
|
44
|
+
*
|
|
45
|
+
* The engine splits a `string` value into words, so it can find the document
|
|
46
|
+
* by any word in the value. It can filter and sort by a `number`, `boolean`,
|
|
47
|
+
* or `enum` field. A `geopoint` value is a latitude and longitude pair. A
|
|
48
|
+
* `vector[N]` value is an embedding with N dimensions. For each list form, the
|
|
49
|
+
* engine indexes every element of the list.
|
|
50
|
+
*
|
|
51
|
+
* The engine stores and compares a `verbatim` value exactly as written, as one
|
|
52
|
+
* piece of text. Because the engine keeps that value whole, it leaves the
|
|
53
|
+
* field out of keyword search, although it can test the whole value in a
|
|
54
|
+
* filter.
|
|
55
|
+
*
|
|
56
|
+
* Add the {@link TextFieldOption} options to a `string` or `string[]` type, or
|
|
57
|
+
* `sortable` alone to a `verbatim` or `verbatim[]` type, as in
|
|
58
|
+
* `string:sortable:pattern` or `verbatim[]:sortable`. The engine stores the
|
|
59
|
+
* options in the order `sortable`, `pattern`, `partial`, whatever their order
|
|
60
|
+
* in the type name. It raises `SCHEMA_INVALID_TYPE` for any other
|
|
61
|
+
* option, such as `number:sortable` or `verbatim:pattern`, and for an option
|
|
62
|
+
* written twice.
|
|
63
|
+
*
|
|
64
|
+
* To sort by a text field, the engine keeps up to the first 512 code points of
|
|
65
|
+
* every document's value in memory, against 8 bytes per document for a number
|
|
66
|
+
* field. For that reason, the engine sorts by a text field only where the
|
|
67
|
+
* field's type includes `sortable`, while it raises `SEARCH_INVALID_FIELD`
|
|
68
|
+
* for a sort on any other text field.
|
|
69
|
+
*
|
|
70
|
+
* @public
|
|
71
|
+
*/
|
|
72
|
+
type FieldType = 'string' | `string${FieldOptionChain<TextFieldOption>}` | 'string[]' | `string[]${FieldOptionChain<TextFieldOption>}` | 'verbatim' | 'verbatim:sortable' | 'verbatim[]' | 'verbatim[]:sortable' | 'number' | 'boolean' | 'enum' | 'geopoint' | `vector[${number}]` | 'number[]' | 'boolean[]' | 'enum[]';
|
|
30
73
|
/**
|
|
31
74
|
* The field layout of an index, written as a plain object.
|
|
32
75
|
*
|
|
@@ -173,6 +216,15 @@ interface IndexConfig {
|
|
|
173
216
|
* insert throughput and one entry per changed spelling.
|
|
174
217
|
*/
|
|
175
218
|
surfaceForms?: boolean;
|
|
219
|
+
/**
|
|
220
|
+
* The engine raises `DOC_VALIDATION_FAILED` for a document whose value in a
|
|
221
|
+
* `verbatim` field, or in a field whose type includes `pattern`, is longer
|
|
222
|
+
* than this many code points. It tests each element of a list on its own.
|
|
223
|
+
* Set a whole number from 1 to 65,536, or leave this unset for a limit of
|
|
224
|
+
* 8,192. For any other value, {@link Narsil.createIndex} throws
|
|
225
|
+
* `CONFIG_INVALID`.
|
|
226
|
+
*/
|
|
227
|
+
patternValueLimit?: number;
|
|
176
228
|
}
|
|
177
229
|
/**
|
|
178
230
|
* BM25 tuning for an index.
|
|
@@ -286,4 +338,4 @@ interface InsertOptions extends WriteOptions {
|
|
|
286
338
|
skipClone?: boolean;
|
|
287
339
|
}
|
|
288
340
|
|
|
289
|
-
export type { AnyDocument as A, BM25Params as B, CustomTokenizer as C, EmbeddingFieldConfig as E,
|
|
341
|
+
export type { AnyDocument as A, BM25Params as B, CustomTokenizer as C, EmbeddingFieldConfig as E, FieldOptionChain as F, IndexConfig as I, PartitionConfig as P, SchemaDefinition as S, TextFieldOption as T, VectorIndexConfig as V, WriteOptions as W, InsertOptions as a, StopWordOverride as b, FieldType as c, ScoringMode as d, VectorQuantizationMode as e, VectorStorageMode as f };
|
package/dist/server.d.ts
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
export { C as ClientErrorCode, a as ClientErrorCodes, E as ErrorCode, b as ErrorCodes, N as NarsilError, c as NarsilErrorCode, S as ServerErrorCode, d as ServerErrorCodes, i as isNarsilError } from './memory-
|
|
2
|
-
import { b as ServerOptions, N as NarsilServer } from './capabilities-
|
|
3
|
-
export { A as ASYNC_IMPORT_CAPABILITY, C as CorsOptions, E as ErrorEnvelope, I as INDEX_LIFECYCLE_CAPABILITY, O as OnRequestHook, R as REBUILD_ANALYSIS_CAPABILITY, c as RequestContext, d as RequestDenial, S as SERVER_CAPABILITIES, e as ServerLimits, T as TASK_CANCEL_CAPABILITY, a as TASK_FILTER_CAPABILITY } from './capabilities-
|
|
4
|
-
import { a as Narsil } from './engine-
|
|
5
|
-
import { d as TaskProgress, b as ImportResult, h as TaskStore, e as TaskRecord } from './tasks-
|
|
6
|
-
export { C as CapabilitiesResponse, a as CreateIndexEmbedding, i as CreateIndexRequest, H as HttpIndexConfig, I as ImportError, M as MemoryStatsResponse, T as TaskListPage, c as TaskListQuery, f as TaskStatus, g as TaskType } from './tasks-
|
|
7
|
-
import './schema-
|
|
1
|
+
export { C as ClientErrorCode, a as ClientErrorCodes, E as ErrorCode, b as ErrorCodes, N as NarsilError, c as NarsilErrorCode, S as ServerErrorCode, d as ServerErrorCodes, i as isNarsilError } from './memory-C7UMCMH3.js';
|
|
2
|
+
import { b as ServerOptions, N as NarsilServer } from './capabilities-Dt-7B4Wz.js';
|
|
3
|
+
export { A as ASYNC_IMPORT_CAPABILITY, C as CorsOptions, E as ErrorEnvelope, I as INDEX_LIFECYCLE_CAPABILITY, O as OnRequestHook, R as REBUILD_ANALYSIS_CAPABILITY, c as RequestContext, d as RequestDenial, S as SERVER_CAPABILITIES, e as ServerLimits, T as TASK_CANCEL_CAPABILITY, a as TASK_FILTER_CAPABILITY } from './capabilities-Dt-7B4Wz.js';
|
|
4
|
+
import { a as Narsil } from './engine-igk0aMpQ.js';
|
|
5
|
+
import { d as TaskProgress, b as ImportResult, h as TaskStore, e as TaskRecord } from './tasks-BZt_zes6.js';
|
|
6
|
+
export { C as CapabilitiesResponse, a as CreateIndexEmbedding, i as CreateIndexRequest, H as HttpIndexConfig, I as ImportError, M as MemoryStatsResponse, T as TaskListPage, c as TaskListQuery, f as TaskStatus, g as TaskType } from './tasks-BZt_zes6.js';
|
|
7
|
+
import './schema-Bgzr4g7b.js';
|
|
8
8
|
import './adapters-79OIa4xm.js';
|
|
9
|
-
import './config-
|
|
10
|
-
import './config-
|
|
11
|
-
import './types-
|
|
9
|
+
import './config-rBpbgTw8.js';
|
|
10
|
+
import './config-Dfanyqqt.js';
|
|
11
|
+
import './types-gOUqhs2F.js';
|
|
12
12
|
import './types-D5OwhtsQ.js';
|
|
13
13
|
|
|
14
14
|
/**
|
package/dist/server.mjs
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import { DEFAULT_MAX_RETAINED_TASKS, loadUWebSockets, resolveCors, authorizerFor, createSharedGateBuffer, gateSlotOfWorker, createRouteRunner, corsHeaderReader, createSharedRequestGate, MAIN_THREAD_GATE_SLOT, registerServerRoutes, DEFAULT_MAX_CONCURRENT_TASKS, DEFAULT_MAX_TASK_PAGE_SIZE, DEFAULT_MAX_IMPORT_ERRORS, DEFAULT_MAX_FETCH_DOCUMENTS, DEFAULT_MAX_RESULT_WINDOW, DEFAULT_MAX_CONCURRENT_REQUESTS, DEFAULT_IMPORT_BATCH_SIZE, DEFAULT_MAX_LINE_BYTES, DEFAULT_MAX_IMPORT_BYTES, DEFAULT_MAX_BODY_BYTES, RUNNING_TASK_TTL_MS, DEFAULT_TASK_PAGE_SIZE, TERMINAL_TASK_TTL_MS, TASK_PROGRESS_WRITE_INTERVAL_MS, serializeNarsilError, createVersionHandler, acceptorOf, createDocumentReadHandlers, sendError, respondError, respondJson, MAX_INDEX_TOUCH_INTERVAL_MS, INDEX_TOUCH_INTERVALS_PER_IDLE_TIMEOUT, clearGateSlot, parseJson, validateCreateIndex, rejectInvalid, validateBatch, serializeBatchResult, validateDocumentBody, validateSuggest, validateQuery, parseTaskListQuery, parseJsonOptional, validateRebalance, sendBinary, IMPORT_FLUSHES_IN_FLIGHT, badRequest, SERVER_CAPABILITIES, toHttpError, MIN_UNBOUNDED_SERVER_LIMIT, MIN_COUNTED_SERVER_LIMIT } from './chunk-
|
|
2
|
-
export { ASYNC_IMPORT_CAPABILITY, INDEX_LIFECYCLE_CAPABILITY, REBUILD_ANALYSIS_CAPABILITY, SERVER_CAPABILITIES, TASK_CANCEL_CAPABILITY, TASK_FILTER_CAPABILITY, httpStatusForNarsilError } from './chunk-
|
|
3
|
-
import { validateIndexName } from './chunk-
|
|
4
|
-
import { engineCoreOf, providedDocId, resolveVectorText } from './chunk-
|
|
5
|
-
import { detectRuntime } from './chunk-
|
|
6
|
-
import './chunk-
|
|
7
|
-
import './chunk-
|
|
1
|
+
import { DEFAULT_MAX_RETAINED_TASKS, loadUWebSockets, resolveCors, authorizerFor, createSharedGateBuffer, gateSlotOfWorker, createRouteRunner, corsHeaderReader, createSharedRequestGate, MAIN_THREAD_GATE_SLOT, registerServerRoutes, DEFAULT_MAX_CONCURRENT_TASKS, DEFAULT_MAX_TASK_PAGE_SIZE, DEFAULT_MAX_IMPORT_ERRORS, DEFAULT_MAX_FETCH_DOCUMENTS, DEFAULT_MAX_RESULT_WINDOW, DEFAULT_MAX_CONCURRENT_REQUESTS, DEFAULT_IMPORT_BATCH_SIZE, DEFAULT_MAX_LINE_BYTES, DEFAULT_MAX_IMPORT_BYTES, DEFAULT_MAX_BODY_BYTES, RUNNING_TASK_TTL_MS, DEFAULT_TASK_PAGE_SIZE, TERMINAL_TASK_TTL_MS, TASK_PROGRESS_WRITE_INTERVAL_MS, serializeNarsilError, createVersionHandler, acceptorOf, createDocumentReadHandlers, sendError, respondError, respondJson, MAX_INDEX_TOUCH_INTERVAL_MS, INDEX_TOUCH_INTERVALS_PER_IDLE_TIMEOUT, clearGateSlot, parseJson, validateCreateIndex, rejectInvalid, validateBatch, serializeBatchResult, validateDocumentBody, validateSuggest, validateQuery, parseTaskListQuery, parseJsonOptional, validateRebalance, sendBinary, IMPORT_FLUSHES_IN_FLIGHT, badRequest, SERVER_CAPABILITIES, toHttpError, MIN_UNBOUNDED_SERVER_LIMIT, MIN_COUNTED_SERVER_LIMIT } from './chunk-2STVUTNA.mjs';
|
|
2
|
+
export { ASYNC_IMPORT_CAPABILITY, INDEX_LIFECYCLE_CAPABILITY, REBUILD_ANALYSIS_CAPABILITY, SERVER_CAPABILITIES, TASK_CANCEL_CAPABILITY, TASK_FILTER_CAPABILITY, httpStatusForNarsilError } from './chunk-2STVUTNA.mjs';
|
|
3
|
+
import { validateIndexName } from './chunk-3JGWULDF.mjs';
|
|
4
|
+
import { engineCoreOf, providedDocId, resolveVectorText } from './chunk-FVLQ63B7.mjs';
|
|
5
|
+
import { detectRuntime } from './chunk-HWQLTLNG.mjs';
|
|
6
|
+
import './chunk-GIVAGD3Q.mjs';
|
|
7
|
+
import './chunk-653BNMAF.mjs';
|
|
8
|
+
import './chunk-TGP5M5R7.mjs';
|
|
8
9
|
import './chunk-YNVIUGF5.mjs';
|
|
10
|
+
import './chunk-U2BKYEC7.mjs';
|
|
11
|
+
import './chunk-OI42GWLR.mjs';
|
|
9
12
|
import { startIdleHeapCleanup } from './chunk-Y3L5MDRV.mjs';
|
|
10
13
|
import { NarsilError, ErrorCodes, ServerErrorCodes, isNarsilError } from './chunk-USKFU7J5.mjs';
|
|
11
14
|
export { ClientErrorCodes, ErrorCodes, NarsilError, ServerErrorCodes, isNarsilError } from './chunk-USKFU7J5.mjs';
|
|
@@ -594,6 +597,7 @@ function mapHttpIndexConfig(http) {
|
|
|
594
597
|
if (http.vectorPromotion !== void 0) config.vectorPromotion = http.vectorPromotion;
|
|
595
598
|
if (http.strict !== void 0) config.strict = http.strict;
|
|
596
599
|
if (http.required !== void 0) config.required = http.required;
|
|
600
|
+
if (http.patternValueLimit !== void 0) config.patternValueLimit = http.patternValueLimit;
|
|
597
601
|
if (http.stopWords !== void 0) {
|
|
598
602
|
if (!Array.isArray(http.stopWords) || http.stopWords.some((w) => typeof w !== "string")) {
|
|
599
603
|
throw new NarsilError(ErrorCodes.CONFIG_INVALID, 'Field "stopWords" must be an array of strings');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { M as MemoryStats } from './memory-
|
|
1
|
+
import { M as MemoryStats } from './memory-C7UMCMH3.js';
|
|
2
2
|
|
|
3
3
|
/** Declarative index configuration accepted over HTTP. Function-valued engine
|
|
4
4
|
* options (custom tokenizer, stopWords-as-function, group reducer, embedding
|
|
@@ -68,6 +68,8 @@ interface HttpIndexConfig {
|
|
|
68
68
|
embedding?: CreateIndexEmbedding;
|
|
69
69
|
/** The server rejects a document that omits any of these fields. */
|
|
70
70
|
required?: string[];
|
|
71
|
+
/** The server returns a `DOC_VALIDATION_FAILED` error for a document whose value in a `verbatim` field, or in a field whose type includes `pattern`, is longer than this many code points. Set a whole number from 1 to 65,536, or leave this unset for a limit of 8,192. */
|
|
72
|
+
patternValueLimit?: number;
|
|
71
73
|
}
|
|
72
74
|
/**
|
|
73
75
|
* One record an import refused, naming the line it came from and why the
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import { loadUWebSockets, childAppOf, createRouteRunner, corsHeaderReader, createSharedRequestGate, registerServerRoutes, sendRelayed, createDocumentReadHandlers, respondJson, SERVER_CAPABILITIES, versionReport, sendError, serverRoutes, parseJson, validateSuggest, rejectInvalid, respondError, validateQuery } from './chunk-
|
|
2
|
-
import { executeListDocuments, executeSuggest, executePreflight, queryBindingOf, executeQuery } from './chunk-
|
|
3
|
-
import './chunk-
|
|
4
|
-
import { resolveProjection, projectionKeepsField, setNestedValue } from './chunk-
|
|
5
|
-
import { extractVectorFieldsFromSchema } from './chunk-
|
|
1
|
+
import { loadUWebSockets, childAppOf, createRouteRunner, corsHeaderReader, createSharedRequestGate, registerServerRoutes, sendRelayed, createDocumentReadHandlers, respondJson, SERVER_CAPABILITIES, versionReport, sendError, serverRoutes, parseJson, validateSuggest, rejectInvalid, respondError, validateQuery } from './chunk-2STVUTNA.mjs';
|
|
2
|
+
import { executeListDocuments, executeSuggest, executePreflight, queryBindingOf, executeQuery } from './chunk-P4DSQ6M4.mjs';
|
|
3
|
+
import './chunk-GIVAGD3Q.mjs';
|
|
4
|
+
import { resolveProjection, projectionKeepsField, setNestedValue } from './chunk-LMO5TJUS.mjs';
|
|
5
|
+
import { extractVectorFieldsFromSchema } from './chunk-653BNMAF.mjs';
|
|
6
6
|
import './chunk-ZJ4CSAB2.mjs';
|
|
7
7
|
import './chunk-YNVIUGF5.mjs';
|
|
8
|
-
import './chunk-
|
|
8
|
+
import './chunk-OI42GWLR.mjs';
|
|
9
9
|
import { ServerErrorCodes, NarsilError, ErrorCodes } from './chunk-USKFU7J5.mjs';
|
|
10
10
|
|
|
11
11
|
// src/server/request-threads/held-vectors.ts
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { openSharedVectorField, MAX_WORKER_COPIES, createVectorStore, osqBitsOf, createHNSWIndex, createOsqQuantizer, osqRecordBytes } from '../chunk-
|
|
1
|
+
import { openSharedVectorField, MAX_WORKER_COPIES, createVectorStore, osqBitsOf, createHNSWIndex, createOsqQuantizer, osqRecordBytes } from '../chunk-YJDQ7NLA.mjs';
|
|
2
2
|
import '../chunk-ZJ4CSAB2.mjs';
|
|
3
3
|
import '../chunk-YNVIUGF5.mjs';
|
|
4
|
-
import '../chunk-
|
|
4
|
+
import '../chunk-OI42GWLR.mjs';
|
|
5
5
|
import '../chunk-USKFU7J5.mjs';
|
|
6
6
|
|
|
7
7
|
// src/vector/worker-copy.ts
|
package/dist/workers/entry.mjs
CHANGED
|
@@ -18,7 +18,7 @@ async function importBootstrapModule(moduleUrl) {
|
|
|
18
18
|
await import(moduleUrl);
|
|
19
19
|
}
|
|
20
20
|
async function stopServingRequests() {
|
|
21
|
-
const { closeRequestThread } = await import('../thread-
|
|
21
|
+
const { closeRequestThread } = await import('../thread-JEVAYETR.mjs');
|
|
22
22
|
closeRequestThread();
|
|
23
23
|
}
|
|
24
24
|
function holdsCopies(executor) {
|
|
@@ -49,7 +49,7 @@ function createActionHandler(executor) {
|
|
|
49
49
|
if (!holdsCopies(executor)) {
|
|
50
50
|
throw new NarsilError(ErrorCodes.CONFIG_INVALID, "This executor holds no copies to answer requests from");
|
|
51
51
|
}
|
|
52
|
-
const starting = import('../thread-
|
|
52
|
+
const starting = import('../thread-JEVAYETR.mjs').then(
|
|
53
53
|
({ serveRequests }) => serveRequests(executor, action.settings)
|
|
54
54
|
);
|
|
55
55
|
serving.start = starting.then(
|
|
@@ -102,7 +102,7 @@ async function setup() {
|
|
|
102
102
|
} catch {
|
|
103
103
|
parentPort = null;
|
|
104
104
|
}
|
|
105
|
-
const { createDirectExecutor } = await import('../direct-executor-
|
|
105
|
+
const { createDirectExecutor } = await import('../direct-executor-GYJEKNV5.mjs');
|
|
106
106
|
const handleAction = createActionHandler(createDirectExecutor({ threadSlot }));
|
|
107
107
|
if (parentPort) {
|
|
108
108
|
const port = parentPort;
|