@delali/narsil 0.1.14 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/NOTICE +54 -0
- package/README.md +38 -972
- package/dist/adapters/filesystem.mjs +1 -1
- package/dist/adapters/indexeddb.mjs +1 -1
- package/dist/{chunk-WISGW24C.mjs → chunk-AUMKFYTG.mjs} +1 -1
- package/dist/{chunk-HRABJLPB.mjs → chunk-BKAI2WXI.mjs} +1 -0
- package/dist/chunk-GHJWC2E5.mjs +9 -0
- package/dist/chunk-KH3YGMVT.mjs +15 -0
- package/dist/{chunk-ALB35PRQ.mjs → chunk-M2EDG55Y.mjs} +8 -0
- package/dist/{chunk-HMO6OMZ3.mjs → chunk-S6IAXOBA.mjs} +1073 -506
- package/dist/chunk-TGP5M5R7.mjs +880 -0
- package/dist/chunk-U2BKYEC7.mjs +254 -0
- package/dist/{chunk-MEW7HD75.mjs → chunk-XAKNSWIK.mjs} +2543 -1154
- package/dist/{config-CojEPOgS.d.ts → config-P27AtSn4.d.ts} +28 -7
- package/dist/direct-executor-2FV3MEDD.mjs +5 -0
- package/dist/distribution/coordinator/etcd.d.ts +2 -2
- package/dist/distribution/coordinator/etcd.mjs +2 -2
- package/dist/distribution/coordinator/in-memory.d.ts +2 -2
- package/dist/distribution.d.ts +10 -4
- package/dist/distribution.mjs +1875 -1772
- package/dist/embeddings/openai.mjs +1 -1
- package/dist/index.browser.mjs +4566 -1783
- package/dist/index.d.ts +14 -5
- package/dist/index.mjs +6 -5
- package/dist/{language-ONQ3iVDf.d.ts → language-CmJBHf1j.d.ts} +4 -1
- package/dist/languages/albanian.d.ts +5 -0
- package/dist/languages/albanian.mjs +103 -0
- package/dist/languages/amharic.d.ts +5 -0
- package/dist/languages/amharic.mjs +240 -0
- package/dist/languages/arabic.d.ts +1 -1
- package/dist/languages/arabic.mjs +939 -154
- package/dist/languages/armenian.d.ts +1 -1
- package/dist/languages/armenian.mjs +275 -243
- package/dist/languages/azerbaijani.d.ts +5 -0
- package/dist/languages/azerbaijani.mjs +152 -0
- package/dist/languages/bambara.d.ts +5 -0
- package/dist/languages/bambara.mjs +60 -0
- package/dist/languages/basque.d.ts +5 -0
- package/dist/languages/basque.mjs +726 -0
- package/dist/languages/belarusian.d.ts +5 -0
- package/dist/languages/belarusian.mjs +100 -0
- package/dist/languages/bengali.d.ts +5 -0
- package/dist/languages/bengali.mjs +128 -0
- package/dist/languages/bosnian.d.ts +5 -0
- package/dist/languages/bosnian.mjs +197 -0
- package/dist/languages/breton.d.ts +5 -0
- package/dist/languages/breton.mjs +96 -0
- package/dist/languages/bulgarian.d.ts +1 -1
- package/dist/languages/bulgarian.mjs +11 -2
- package/dist/languages/burmese.d.ts +5 -0
- package/dist/languages/burmese.mjs +57 -0
- package/dist/languages/catalan.d.ts +5 -0
- package/dist/languages/catalan.mjs +987 -0
- package/dist/languages/chinese.d.ts +1 -1
- package/dist/languages/chinese.mjs +4 -3
- package/dist/languages/croatian.d.ts +5 -0
- package/dist/languages/croatian.mjs +191 -0
- package/dist/languages/czech.d.ts +5 -0
- package/dist/languages/czech.mjs +628 -0
- package/dist/languages/dagbani.d.ts +1 -1
- package/dist/languages/dagbani.mjs +11 -2
- package/dist/languages/danish.d.ts +1 -1
- package/dist/languages/danish.mjs +215 -110
- package/dist/languages/dutch.d.ts +1 -1
- package/dist/languages/dutch.mjs +1248 -163
- package/dist/languages/english.d.ts +1 -1
- package/dist/languages/english.mjs +2 -1
- package/dist/languages/esperanto.d.ts +5 -0
- package/dist/languages/esperanto.mjs +689 -0
- package/dist/languages/estonian.d.ts +5 -0
- package/dist/languages/estonian.mjs +2160 -0
- package/dist/languages/ewe.d.ts +1 -1
- package/dist/languages/ewe.mjs +11 -2
- package/dist/languages/faroese.d.ts +5 -0
- package/dist/languages/faroese.mjs +93 -0
- package/dist/languages/fijian.d.ts +5 -0
- package/dist/languages/fijian.mjs +55 -0
- package/dist/languages/finnish.d.ts +1 -1
- package/dist/languages/finnish.mjs +528 -263
- package/dist/languages/french.d.ts +1 -1
- package/dist/languages/french.mjs +950 -437
- package/dist/languages/ga.d.ts +1 -1
- package/dist/languages/ga.mjs +2 -1
- package/dist/languages/galician.d.ts +5 -0
- package/dist/languages/galician.mjs +172 -0
- package/dist/languages/georgian.d.ts +5 -0
- package/dist/languages/georgian.mjs +91 -0
- package/dist/languages/german.d.ts +1 -1
- package/dist/languages/german.mjs +432 -162
- package/dist/languages/greek.d.ts +1 -1
- package/dist/languages/greek.mjs +1970 -281
- package/dist/languages/guarani.d.ts +5 -0
- package/dist/languages/guarani.mjs +132 -0
- package/dist/languages/gujarati.d.ts +5 -0
- package/dist/languages/gujarati.mjs +234 -0
- package/dist/languages/haitian-creole.d.ts +5 -0
- package/dist/languages/haitian-creole.mjs +106 -0
- package/dist/languages/hausa.d.ts +1 -1
- package/dist/languages/hausa.mjs +2 -1
- package/dist/languages/hawaiian.d.ts +5 -0
- package/dist/languages/hawaiian.mjs +69 -0
- package/dist/languages/hebrew.d.ts +5 -0
- package/dist/languages/hebrew.mjs +213 -0
- package/dist/languages/hindi.d.ts +1 -1
- package/dist/languages/hindi.mjs +175 -97
- package/dist/languages/hungarian.d.ts +1 -1
- package/dist/languages/hungarian.mjs +412 -326
- package/dist/languages/icelandic.d.ts +5 -0
- package/dist/languages/icelandic.mjs +161 -0
- package/dist/languages/igbo.d.ts +1 -1
- package/dist/languages/igbo.mjs +2 -1
- package/dist/languages/indonesian.d.ts +1 -1
- package/dist/languages/indonesian.mjs +329 -137
- package/dist/languages/irish.d.ts +1 -1
- package/dist/languages/irish.mjs +223 -139
- package/dist/languages/italian.d.ts +1 -1
- package/dist/languages/italian.mjs +703 -406
- package/dist/languages/japanese.d.ts +1 -1
- package/dist/languages/japanese.mjs +5 -108
- package/dist/languages/kannada.d.ts +5 -0
- package/dist/languages/kannada.mjs +94 -0
- package/dist/languages/kazakh.d.ts +5 -0
- package/dist/languages/kazakh.mjs +90 -0
- package/dist/languages/khmer.d.ts +5 -0
- package/dist/languages/khmer.mjs +181 -0
- package/dist/languages/kinyarwanda.d.ts +5 -0
- package/dist/languages/kinyarwanda.mjs +99 -0
- package/dist/languages/kirundi.d.ts +5 -0
- package/dist/languages/kirundi.mjs +92 -0
- package/dist/languages/korean.d.ts +5 -0
- package/dist/languages/korean.mjs +252 -0
- package/dist/languages/kurmanji.d.ts +5 -0
- package/dist/languages/kurmanji.mjs +50 -0
- package/dist/languages/kyrgyz.d.ts +5 -0
- package/dist/languages/kyrgyz.mjs +108 -0
- package/dist/languages/lao.d.ts +5 -0
- package/dist/languages/lao.mjs +63 -0
- package/dist/languages/latin.d.ts +5 -0
- package/dist/languages/latin.mjs +69 -0
- package/dist/languages/latvian.d.ts +5 -0
- package/dist/languages/latvian.mjs +173 -0
- package/dist/languages/lingala.d.ts +5 -0
- package/dist/languages/lingala.mjs +61 -0
- package/dist/languages/lithuanian.d.ts +5 -0
- package/dist/languages/lithuanian.mjs +571 -0
- package/dist/languages/luxembourgish.d.ts +5 -0
- package/dist/languages/luxembourgish.mjs +214 -0
- package/dist/languages/macedonian.d.ts +5 -0
- package/dist/languages/macedonian.mjs +808 -0
- package/dist/languages/malagasy.d.ts +5 -0
- package/dist/languages/malagasy.mjs +67 -0
- package/dist/languages/malay.d.ts +5 -0
- package/dist/languages/malay.mjs +482 -0
- package/dist/languages/malayalam.d.ts +5 -0
- package/dist/languages/malayalam.mjs +122 -0
- package/dist/languages/maltese.d.ts +5 -0
- package/dist/languages/maltese.mjs +139 -0
- package/dist/languages/maori.d.ts +5 -0
- package/dist/languages/maori.mjs +79 -0
- package/dist/languages/marathi.d.ts +5 -0
- package/dist/languages/marathi.mjs +111 -0
- package/dist/languages/nepali.d.ts +1 -1
- package/dist/languages/nepali.mjs +209 -99
- package/dist/languages/norwegian.d.ts +1 -1
- package/dist/languages/norwegian.mjs +218 -85
- package/dist/languages/oromo.d.ts +5 -0
- package/dist/languages/oromo.mjs +78 -0
- package/dist/languages/persian.d.ts +5 -0
- package/dist/languages/persian.mjs +710 -0
- package/dist/languages/polish.d.ts +5 -0
- package/dist/languages/polish.mjs +614 -0
- package/dist/languages/portuguese.d.ts +1 -1
- package/dist/languages/portuguese.mjs +613 -380
- package/dist/languages/punjabi.d.ts +5 -0
- package/dist/languages/punjabi.mjs +197 -0
- package/dist/languages/romanian.d.ts +1 -1
- package/dist/languages/romanian.mjs +561 -382
- package/dist/languages/russian.d.ts +1 -1
- package/dist/languages/russian.mjs +373 -244
- package/dist/languages/samoan.d.ts +5 -0
- package/dist/languages/samoan.mjs +63 -0
- package/dist/languages/sanskrit.d.ts +1 -1
- package/dist/languages/sanskrit.mjs +2 -2
- package/dist/languages/scottish-gaelic.d.ts +5 -0
- package/dist/languages/scottish-gaelic.mjs +370 -0
- package/dist/languages/serbian.d.ts +1 -1
- package/dist/languages/serbian.mjs +3635 -155
- package/dist/languages/shona.d.ts +5 -0
- package/dist/languages/shona.mjs +91 -0
- package/dist/languages/sinhala.d.ts +5 -0
- package/dist/languages/sinhala.mjs +182 -0
- package/dist/languages/slovak.d.ts +5 -0
- package/dist/languages/slovak.mjs +430 -0
- package/dist/languages/slovenian.d.ts +1 -1
- package/dist/languages/slovenian.mjs +11 -2
- package/dist/languages/sorani.d.ts +5 -0
- package/dist/languages/sorani.mjs +156 -0
- package/dist/languages/spanish.d.ts +1 -1
- package/dist/languages/spanish.mjs +676 -374
- package/dist/languages/swahili.d.ts +1 -1
- package/dist/languages/swahili.mjs +2 -1
- package/dist/languages/swedish.d.ts +1 -1
- package/dist/languages/swedish.mjs +237 -95
- package/dist/languages/tagalog.d.ts +5 -0
- package/dist/languages/tagalog.mjs +159 -0
- package/dist/languages/tamil.d.ts +1 -1
- package/dist/languages/tamil.mjs +836 -64
- package/dist/languages/tatar.d.ts +5 -0
- package/dist/languages/tatar.mjs +1017 -0
- package/dist/languages/telugu.d.ts +5 -0
- package/dist/languages/telugu.mjs +62 -0
- package/dist/languages/thai.d.ts +5 -0
- package/dist/languages/thai.mjs +65 -0
- package/dist/languages/tibetan.d.ts +5 -0
- package/dist/languages/tibetan.mjs +119 -0
- package/dist/languages/tigrinya.d.ts +5 -0
- package/dist/languages/tigrinya.mjs +194 -0
- package/dist/languages/tongan.d.ts +5 -0
- package/dist/languages/tongan.mjs +56 -0
- package/dist/languages/turkish.d.ts +1 -1
- package/dist/languages/turkish.mjs +1246 -393
- package/dist/languages/twi.d.ts +1 -1
- package/dist/languages/twi.mjs +13 -2
- package/dist/languages/ukrainian.d.ts +1 -1
- package/dist/languages/ukrainian.mjs +125 -47
- package/dist/languages/urdu.d.ts +5 -0
- package/dist/languages/urdu.mjs +528 -0
- package/dist/languages/vietnamese.d.ts +5 -0
- package/dist/languages/vietnamese.mjs +277 -0
- package/dist/languages/welsh.d.ts +5 -0
- package/dist/languages/welsh.mjs +446 -0
- package/dist/languages/wolof.d.ts +5 -0
- package/dist/languages/wolof.mjs +79 -0
- package/dist/languages/xhosa.d.ts +5 -0
- package/dist/languages/xhosa.mjs +95 -0
- package/dist/languages/yoruba.d.ts +1 -1
- package/dist/languages/yoruba.mjs +1 -0
- package/dist/languages/zulu.d.ts +1 -1
- package/dist/languages/zulu.mjs +2 -1
- package/dist/narsil-CMZRPDlQ.d.ts +159 -0
- package/dist/persistence/durability/checkpoint-worker.d.ts +13 -0
- package/dist/persistence/durability/checkpoint-worker.mjs +6 -5
- package/dist/{schema-DCgkO1j4.d.ts → schema-BnvLvjRp.d.ts} +5 -3
- package/dist/server.d.ts +12 -3
- package/dist/server.mjs +183 -64
- package/dist/{types-DHX6zGeD.d.ts → types-BRTcBgAp.d.ts} +1 -1
- package/dist/workers/entry.mjs +2 -2
- package/package.json +10 -3
- package/dist/chunk-TW6BXTOL.mjs +0 -338
- package/dist/direct-executor-E52FFGDE.mjs +0 -4
- package/dist/narsil-D-84Nvm4.d.ts +0 -72
package/dist/server.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { NarsilError, ErrorCodes } from './chunk-
|
|
1
|
+
import { NarsilError, ErrorCodes } from './chunk-M2EDG55Y.mjs';
|
|
2
2
|
import { randomUUID } from 'crypto';
|
|
3
3
|
|
|
4
4
|
// src/server/cors.ts
|
|
@@ -81,7 +81,18 @@ var STATUS_BY_CODE = {
|
|
|
81
81
|
QUERY_ROUTING_FAILED: 503,
|
|
82
82
|
QUERY_PARTIAL_FAILURE: 503,
|
|
83
83
|
QUERY_NODE_TIMEOUT: 503,
|
|
84
|
-
QUERY_NO_ACTIVE_REPLICA: 503
|
|
84
|
+
QUERY_NO_ACTIVE_REPLICA: 503,
|
|
85
|
+
REPLICATION_ENTRY_INVALID: 503,
|
|
86
|
+
REPLICATION_INSYNC_REMOVAL_FAILED: 503,
|
|
87
|
+
REPLICATION_ROLLBACK_FAILED: 503,
|
|
88
|
+
REPLICATION_LOG_FULL: 503,
|
|
89
|
+
REPLICATION_ENTRY_CORRUPT: 503,
|
|
90
|
+
REPLICATION_SNAPSHOT_CORRUPT: 503,
|
|
91
|
+
REPLICATION_TERM_MISMATCH: 503,
|
|
92
|
+
REPLICATION_SYNC_FAILED: 503,
|
|
93
|
+
PARTITION_NOT_PRIMARY: 503,
|
|
94
|
+
PARTITION_UNASSIGNED: 503,
|
|
95
|
+
INSUFFICIENT_REPLICAS: 503
|
|
85
96
|
};
|
|
86
97
|
function httpStatusForNarsilError(code) {
|
|
87
98
|
return STATUS_BY_CODE[code] ?? 500;
|
|
@@ -118,11 +129,31 @@ var STATUS_TEXT = {
|
|
|
118
129
|
500: "500 Internal Server Error",
|
|
119
130
|
503: "503 Service Unavailable"
|
|
120
131
|
};
|
|
132
|
+
var STREAM_THRESHOLD = 64 * 1024;
|
|
121
133
|
function statusLine(status) {
|
|
122
134
|
return STATUS_TEXT[status] ?? `${status}`;
|
|
123
135
|
}
|
|
124
|
-
function
|
|
136
|
+
function streamBody(res, abort, body, status, contentType) {
|
|
137
|
+
if (abort.aborted) return;
|
|
138
|
+
const totalSize = body.byteLength;
|
|
139
|
+
res.cork(() => {
|
|
140
|
+
res.writeStatus(statusLine(status)).writeHeader("Content-Type", contentType);
|
|
141
|
+
const startOffset = res.getWriteOffset();
|
|
142
|
+
const [, done] = res.tryEnd(body, totalSize);
|
|
143
|
+
if (done) return;
|
|
144
|
+
res.onWritable((offset) => {
|
|
145
|
+
if (abort.aborted) return true;
|
|
146
|
+
const [retryOk] = res.tryEnd(body.subarray(offset - startOffset), totalSize);
|
|
147
|
+
return retryOk;
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
function sendJson(res, data, status = 200, abort) {
|
|
125
152
|
const payload = JSON.stringify(data);
|
|
153
|
+
if (abort && payload !== void 0 && Buffer.byteLength(payload) >= STREAM_THRESHOLD) {
|
|
154
|
+
streamBody(res, abort, Buffer.from(payload, "utf8"), status, "application/json");
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
126
157
|
res.cork(() => {
|
|
127
158
|
res.writeStatus(statusLine(status)).writeHeader("Content-Type", "application/json").end(payload);
|
|
128
159
|
});
|
|
@@ -134,10 +165,8 @@ function sendError(res, status, code, message, details) {
|
|
|
134
165
|
res.writeStatus(statusLine(status)).writeHeader("Content-Type", "application/json").end(payload);
|
|
135
166
|
});
|
|
136
167
|
}
|
|
137
|
-
function sendBinary(res, data, status = 200) {
|
|
138
|
-
res
|
|
139
|
-
res.writeStatus(statusLine(status)).writeHeader("Content-Type", "application/octet-stream").end(data);
|
|
140
|
-
});
|
|
168
|
+
function sendBinary(res, data, abort, status = 200) {
|
|
169
|
+
streamBody(res, abort, data, status, "application/octet-stream");
|
|
141
170
|
}
|
|
142
171
|
|
|
143
172
|
// src/server/handler-utils.ts
|
|
@@ -171,11 +200,15 @@ function respondError(ctx, err) {
|
|
|
171
200
|
}
|
|
172
201
|
function respondJson(ctx, data, status = 200) {
|
|
173
202
|
if (ctx.abort.aborted) return;
|
|
174
|
-
sendJson(ctx.res, data, status);
|
|
203
|
+
sendJson(ctx.res, data, status, ctx.abort);
|
|
175
204
|
}
|
|
176
205
|
function badRequest(res, message, details) {
|
|
177
206
|
sendError(res, 400, ServerErrorCodes.INVALID_REQUEST, message, details);
|
|
178
207
|
}
|
|
208
|
+
function rejectInvalid(ctx, failure) {
|
|
209
|
+
if (ctx.abort.aborted) return;
|
|
210
|
+
badRequest(ctx.res, failure.message, failure.details);
|
|
211
|
+
}
|
|
179
212
|
function serializeBatchResult(result) {
|
|
180
213
|
return {
|
|
181
214
|
succeeded: result.succeeded,
|
|
@@ -186,6 +219,98 @@ function serializeBatchResult(result) {
|
|
|
186
219
|
};
|
|
187
220
|
}
|
|
188
221
|
|
|
222
|
+
// src/server/validation.ts
|
|
223
|
+
function isPlainObject(value) {
|
|
224
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
225
|
+
}
|
|
226
|
+
function overWindow(field, value, maxWindow) {
|
|
227
|
+
if (typeof value === "number" && value > maxWindow) {
|
|
228
|
+
return {
|
|
229
|
+
message: `Field "${field}" exceeds the maximum result window of ${maxWindow}`,
|
|
230
|
+
details: { value, limit: maxWindow }
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
return null;
|
|
234
|
+
}
|
|
235
|
+
function validateQuery(params, maxWindow) {
|
|
236
|
+
if (params.group && typeof params.group === "object" && "reduce" in params.group) {
|
|
237
|
+
return {
|
|
238
|
+
message: 'Custom group reducers are not available over HTTP; use "group.fields" and "group.maxPerGroup" only'
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
const rowBound = overWindow("limit", params.limit, maxWindow) ?? overWindow("offset", params.offset, maxWindow);
|
|
242
|
+
if (rowBound) return rowBound;
|
|
243
|
+
if (params.group && typeof params.group === "object") {
|
|
244
|
+
const grouped = overWindow("group.maxPerGroup", params.group.maxPerGroup, maxWindow);
|
|
245
|
+
if (grouped) return grouped;
|
|
246
|
+
}
|
|
247
|
+
if (params.facets && typeof params.facets === "object") {
|
|
248
|
+
for (const [field, facet] of Object.entries(params.facets)) {
|
|
249
|
+
if (facet && typeof facet === "object") {
|
|
250
|
+
const faceted = overWindow(`facets.${field}.limit`, facet.limit, maxWindow);
|
|
251
|
+
if (faceted) return faceted;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
return null;
|
|
256
|
+
}
|
|
257
|
+
function validateSuggest(params) {
|
|
258
|
+
if (typeof params.prefix !== "string") {
|
|
259
|
+
return { message: 'Field "prefix" is required and must be a string' };
|
|
260
|
+
}
|
|
261
|
+
return null;
|
|
262
|
+
}
|
|
263
|
+
function validateDocumentBody(body) {
|
|
264
|
+
if (!isPlainObject(body.document)) {
|
|
265
|
+
return { message: 'Field "document" is required and must be an object' };
|
|
266
|
+
}
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
function validateMultiGet(body, maxFetch) {
|
|
270
|
+
if (!Array.isArray(body.docIds)) {
|
|
271
|
+
return { message: 'Field "docIds" is required and must be an array of strings' };
|
|
272
|
+
}
|
|
273
|
+
if (body.docIds.length > maxFetch) {
|
|
274
|
+
return {
|
|
275
|
+
message: `Field "docIds" exceeds the maximum of ${maxFetch} ids per request`,
|
|
276
|
+
details: { count: body.docIds.length, limit: maxFetch }
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
return null;
|
|
280
|
+
}
|
|
281
|
+
function validateBatch(body) {
|
|
282
|
+
const action = body.action ?? "insert";
|
|
283
|
+
if (action === "insert") {
|
|
284
|
+
if (!Array.isArray(body.documents)) return { message: 'Batch insert requires a "documents" array' };
|
|
285
|
+
return null;
|
|
286
|
+
}
|
|
287
|
+
if (action === "update") {
|
|
288
|
+
if (!Array.isArray(body.updates)) return { message: 'Batch update requires an "updates" array' };
|
|
289
|
+
return null;
|
|
290
|
+
}
|
|
291
|
+
if (action === "delete") {
|
|
292
|
+
if (!Array.isArray(body.docIds)) return { message: 'Batch delete requires a "docIds" array' };
|
|
293
|
+
return null;
|
|
294
|
+
}
|
|
295
|
+
return { message: 'Field "action" must be one of "insert", "update", or "delete"' };
|
|
296
|
+
}
|
|
297
|
+
function validateCreateIndex(body) {
|
|
298
|
+
if (typeof body.name !== "string" || body.name.length === 0) {
|
|
299
|
+
return { message: 'Field "name" is required and must be a non-empty string' };
|
|
300
|
+
}
|
|
301
|
+
if (!isPlainObject(body.config)) {
|
|
302
|
+
return { message: 'Field "config" is required and must be an object' };
|
|
303
|
+
}
|
|
304
|
+
return null;
|
|
305
|
+
}
|
|
306
|
+
function validateRebalance(body) {
|
|
307
|
+
const target = body.targetPartitionCount;
|
|
308
|
+
if (typeof target !== "number" || !Number.isInteger(target) || target <= 0) {
|
|
309
|
+
return { message: 'Field "targetPartitionCount" is required and must be a positive integer' };
|
|
310
|
+
}
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
|
|
189
314
|
// src/server/handlers/admin.ts
|
|
190
315
|
function taskResponse(record) {
|
|
191
316
|
return { taskId: record.id, type: record.type, status: record.status };
|
|
@@ -204,7 +329,7 @@ function createAdminHandlers(deps) {
|
|
|
204
329
|
try {
|
|
205
330
|
const bytes = await engine.snapshot(ctx.params[0]);
|
|
206
331
|
if (ctx.abort.aborted) return;
|
|
207
|
-
sendBinary(ctx.res, bytes);
|
|
332
|
+
sendBinary(ctx.res, bytes, ctx.abort);
|
|
208
333
|
} catch (err) {
|
|
209
334
|
respondError(ctx, err);
|
|
210
335
|
}
|
|
@@ -262,11 +387,12 @@ function createAdminHandlers(deps) {
|
|
|
262
387
|
async function rebalance(ctx) {
|
|
263
388
|
const body = parseJsonOptional(ctx);
|
|
264
389
|
if (!body) return;
|
|
265
|
-
const
|
|
266
|
-
if (
|
|
267
|
-
|
|
390
|
+
const failure = validateRebalance(body);
|
|
391
|
+
if (failure) {
|
|
392
|
+
rejectInvalid(ctx, failure);
|
|
268
393
|
return;
|
|
269
394
|
}
|
|
395
|
+
const target = body.targetPartitionCount;
|
|
270
396
|
const name = ctx.params[0];
|
|
271
397
|
try {
|
|
272
398
|
requireIndexExists(name);
|
|
@@ -315,16 +441,14 @@ function createAdminHandlers(deps) {
|
|
|
315
441
|
}
|
|
316
442
|
|
|
317
443
|
// src/server/handlers/documents.ts
|
|
318
|
-
function isPlainObject(value) {
|
|
319
|
-
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
320
|
-
}
|
|
321
444
|
function createDocumentHandlers(deps) {
|
|
322
|
-
const { engine } = deps;
|
|
445
|
+
const { engine, limits } = deps;
|
|
323
446
|
async function insert(ctx) {
|
|
324
447
|
const body = parseJson(ctx);
|
|
325
448
|
if (!body) return;
|
|
326
|
-
|
|
327
|
-
|
|
449
|
+
const failure = validateDocumentBody(body);
|
|
450
|
+
if (failure) {
|
|
451
|
+
rejectInvalid(ctx, failure);
|
|
328
452
|
return;
|
|
329
453
|
}
|
|
330
454
|
try {
|
|
@@ -356,8 +480,9 @@ function createDocumentHandlers(deps) {
|
|
|
356
480
|
async function put(ctx) {
|
|
357
481
|
const body = parseJson(ctx);
|
|
358
482
|
if (!body) return;
|
|
359
|
-
|
|
360
|
-
|
|
483
|
+
const failure = validateDocumentBody(body);
|
|
484
|
+
if (failure) {
|
|
485
|
+
rejectInvalid(ctx, failure);
|
|
361
486
|
return;
|
|
362
487
|
}
|
|
363
488
|
const [name, id] = ctx.params;
|
|
@@ -376,8 +501,9 @@ function createDocumentHandlers(deps) {
|
|
|
376
501
|
async function patch(ctx) {
|
|
377
502
|
const body = parseJson(ctx);
|
|
378
503
|
if (!body) return;
|
|
379
|
-
|
|
380
|
-
|
|
504
|
+
const failure = validateDocumentBody(body);
|
|
505
|
+
if (failure) {
|
|
506
|
+
rejectInvalid(ctx, failure);
|
|
381
507
|
return;
|
|
382
508
|
}
|
|
383
509
|
try {
|
|
@@ -405,8 +531,9 @@ function createDocumentHandlers(deps) {
|
|
|
405
531
|
async function multiGet(ctx) {
|
|
406
532
|
const body = parseJson(ctx);
|
|
407
533
|
if (!body) return;
|
|
408
|
-
|
|
409
|
-
|
|
534
|
+
const failure = validateMultiGet(body, limits.maxFetchDocuments);
|
|
535
|
+
if (failure) {
|
|
536
|
+
rejectInvalid(ctx, failure);
|
|
410
537
|
return;
|
|
411
538
|
}
|
|
412
539
|
try {
|
|
@@ -421,28 +548,22 @@ function createDocumentHandlers(deps) {
|
|
|
421
548
|
async function batch(ctx) {
|
|
422
549
|
const body = parseJson(ctx);
|
|
423
550
|
if (!body) return;
|
|
551
|
+
const failure = validateBatch(body);
|
|
552
|
+
if (failure) {
|
|
553
|
+
rejectInvalid(ctx, failure);
|
|
554
|
+
return;
|
|
555
|
+
}
|
|
424
556
|
const action = body.action ?? "insert";
|
|
425
557
|
try {
|
|
426
|
-
if (action === "
|
|
427
|
-
|
|
428
|
-
badRequest(ctx.res, 'Batch insert requires a "documents" array');
|
|
429
|
-
return;
|
|
430
|
-
}
|
|
431
|
-
respondJson(ctx, serializeBatchResult(await engine.insertBatch(ctx.params[0], body.documents, body.options)));
|
|
432
|
-
} else if (action === "update") {
|
|
433
|
-
if (!Array.isArray(body.updates)) {
|
|
434
|
-
badRequest(ctx.res, 'Batch update requires an "updates" array');
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
|
-
respondJson(ctx, serializeBatchResult(await engine.updateBatch(ctx.params[0], body.updates)));
|
|
558
|
+
if (action === "update") {
|
|
559
|
+
respondJson(ctx, serializeBatchResult(await engine.updateBatch(ctx.params[0], body.updates ?? [])));
|
|
438
560
|
} else if (action === "delete") {
|
|
439
|
-
|
|
440
|
-
badRequest(ctx.res, 'Batch delete requires a "docIds" array');
|
|
441
|
-
return;
|
|
442
|
-
}
|
|
443
|
-
respondJson(ctx, serializeBatchResult(await engine.removeBatch(ctx.params[0], body.docIds)));
|
|
561
|
+
respondJson(ctx, serializeBatchResult(await engine.removeBatch(ctx.params[0], body.docIds ?? [])));
|
|
444
562
|
} else {
|
|
445
|
-
|
|
563
|
+
respondJson(
|
|
564
|
+
ctx,
|
|
565
|
+
serializeBatchResult(await engine.insertBatch(ctx.params[0], body.documents ?? [], body.options))
|
|
566
|
+
);
|
|
446
567
|
}
|
|
447
568
|
} catch (err) {
|
|
448
569
|
respondError(ctx, err);
|
|
@@ -627,12 +748,9 @@ function createIndexHandlers(deps) {
|
|
|
627
748
|
async function create(ctx) {
|
|
628
749
|
const body = parseJson(ctx);
|
|
629
750
|
if (!body) return;
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
}
|
|
634
|
-
if (typeof body.config !== "object" || body.config === null) {
|
|
635
|
-
badRequest(ctx.res, 'Field "config" is required and must be an object');
|
|
751
|
+
const failure = validateCreateIndex(body);
|
|
752
|
+
if (failure) {
|
|
753
|
+
rejectInvalid(ctx, failure);
|
|
636
754
|
return;
|
|
637
755
|
}
|
|
638
756
|
try {
|
|
@@ -684,22 +802,16 @@ function createIndexHandlers(deps) {
|
|
|
684
802
|
}
|
|
685
803
|
|
|
686
804
|
// src/server/handlers/search.ts
|
|
687
|
-
function rejectsCustomReducer(ctx, params) {
|
|
688
|
-
if (params.group && typeof params.group === "object" && "reduce" in params.group) {
|
|
689
|
-
badRequest(
|
|
690
|
-
ctx.res,
|
|
691
|
-
'Custom group reducers are not available over HTTP; use "group.fields" and "group.maxPerGroup" only'
|
|
692
|
-
);
|
|
693
|
-
return true;
|
|
694
|
-
}
|
|
695
|
-
return false;
|
|
696
|
-
}
|
|
697
805
|
function createSearchHandlers(deps) {
|
|
698
|
-
const { engine } = deps;
|
|
806
|
+
const { engine, limits } = deps;
|
|
699
807
|
async function search(ctx) {
|
|
700
808
|
const params = parseJson(ctx);
|
|
701
809
|
if (!params) return;
|
|
702
|
-
|
|
810
|
+
const failure = validateQuery(params, limits.maxResultWindow);
|
|
811
|
+
if (failure) {
|
|
812
|
+
rejectInvalid(ctx, failure);
|
|
813
|
+
return;
|
|
814
|
+
}
|
|
703
815
|
try {
|
|
704
816
|
respondJson(ctx, await engine.query(ctx.params[0], params));
|
|
705
817
|
} catch (err) {
|
|
@@ -709,7 +821,11 @@ function createSearchHandlers(deps) {
|
|
|
709
821
|
async function preflight(ctx) {
|
|
710
822
|
const params = parseJson(ctx);
|
|
711
823
|
if (!params) return;
|
|
712
|
-
|
|
824
|
+
const failure = validateQuery(params, limits.maxResultWindow);
|
|
825
|
+
if (failure) {
|
|
826
|
+
rejectInvalid(ctx, failure);
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
713
829
|
try {
|
|
714
830
|
respondJson(ctx, await engine.preflight(ctx.params[0], params));
|
|
715
831
|
} catch (err) {
|
|
@@ -719,8 +835,9 @@ function createSearchHandlers(deps) {
|
|
|
719
835
|
async function suggest(ctx) {
|
|
720
836
|
const params = parseJson(ctx);
|
|
721
837
|
if (!params) return;
|
|
722
|
-
|
|
723
|
-
|
|
838
|
+
const failure = validateSuggest(params);
|
|
839
|
+
if (failure) {
|
|
840
|
+
rejectInvalid(ctx, failure);
|
|
724
841
|
return;
|
|
725
842
|
}
|
|
726
843
|
try {
|
|
@@ -1007,7 +1124,9 @@ function resolveLimits(limits) {
|
|
|
1007
1124
|
maxImportBytes: limits?.maxImportBytes ?? 100 * MB,
|
|
1008
1125
|
maxLineBytes: limits?.maxLineBytes ?? 4 * MB,
|
|
1009
1126
|
importBatchSize: limits?.importBatchSize ?? 1e3,
|
|
1010
|
-
maxConcurrentRequests: limits?.maxConcurrentRequests ?? 0
|
|
1127
|
+
maxConcurrentRequests: limits?.maxConcurrentRequests ?? 0,
|
|
1128
|
+
maxResultWindow: limits?.maxResultWindow ?? 1e4,
|
|
1129
|
+
maxFetchDocuments: limits?.maxFetchDocuments ?? 1e4
|
|
1011
1130
|
};
|
|
1012
1131
|
}
|
|
1013
1132
|
function resolveBuild(build) {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { b as SchemaDefinition } from './schema-BnvLvjRp.js';
|
|
2
2
|
|
|
3
3
|
type NodeRole = 'data' | 'coordinator' | 'controller';
|
|
4
4
|
type PartitionState = 'UNASSIGNED' | 'INITIALISING' | 'ACTIVE' | 'MIGRATING' | 'DECOMMISSIONING';
|
package/dist/workers/entry.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { isValidWorkerAction } from '../chunk-
|
|
1
|
+
import { isValidWorkerAction } from '../chunk-BKAI2WXI.mjs';
|
|
2
2
|
|
|
3
3
|
// src/workers/worker-entry.ts
|
|
4
4
|
function startWorker() {
|
|
@@ -15,7 +15,7 @@ async function setup() {
|
|
|
15
15
|
} catch {
|
|
16
16
|
parentPort = null;
|
|
17
17
|
}
|
|
18
|
-
const { createDirectExecutor } = await import('../direct-executor-
|
|
18
|
+
const { createDirectExecutor } = await import('../direct-executor-2FV3MEDD.mjs');
|
|
19
19
|
const executor = createDirectExecutor();
|
|
20
20
|
function buildErrorResponse(requestId, code, message) {
|
|
21
21
|
return { type: "error", requestId, code, message };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@delali/narsil",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "A distributed full-text search engine with cross-language portable binary format.",
|
|
6
6
|
"author": "Delali (https://sondelali.com)",
|
|
@@ -109,7 +109,8 @@
|
|
|
109
109
|
},
|
|
110
110
|
"files": [
|
|
111
111
|
"dist/",
|
|
112
|
-
"LICENSE"
|
|
112
|
+
"LICENSE",
|
|
113
|
+
"NOTICE"
|
|
113
114
|
],
|
|
114
115
|
"dependencies": {
|
|
115
116
|
"@msgpack/msgpack": "3.1.1"
|
|
@@ -122,6 +123,7 @@
|
|
|
122
123
|
"fflate": "0.8.3",
|
|
123
124
|
"selfsigned": "5.5.0",
|
|
124
125
|
"tsup": "8.5.1",
|
|
126
|
+
"tsx": "4.21.0",
|
|
125
127
|
"typescript": "5.9.3",
|
|
126
128
|
"uWebSockets.js": "github:uNetworking/uWebSockets.js#v20.58.0",
|
|
127
129
|
"vitest": "4.0.18",
|
|
@@ -149,10 +151,15 @@
|
|
|
149
151
|
"test:recall": "vitest run src/__tests__/vector/recall.test.ts",
|
|
150
152
|
"test:embeddings": "NARSIL_TEST_EMBEDDINGS=1 vitest run embedding-e2e",
|
|
151
153
|
"bench": "vitest bench",
|
|
154
|
+
"stemmers": "tsx snowball/build.ts",
|
|
155
|
+
"revisions": "tsx scripts/analysis-revisions.ts",
|
|
156
|
+
"revisions:write": "tsx scripts/analysis-revisions.ts --write",
|
|
157
|
+
"lookalikes": "tsx scripts/lookalike-counts.ts",
|
|
158
|
+
"lookalikes:collect": "tsx scripts/lookalike-counts.ts --collect",
|
|
152
159
|
"lint": "biome check src/",
|
|
153
160
|
"typecheck:src": "tsc --noEmit",
|
|
154
161
|
"typecheck:tests": "tsc --noEmit -p tsconfig.test.json",
|
|
155
|
-
"typecheck:tooling": "tsc --noEmit -p scripts/tsconfig.json && tsc --noEmit -p benchmarks/tsconfig.json && tsc --noEmit -p wasm/tsconfig.json",
|
|
162
|
+
"typecheck:tooling": "tsc --noEmit -p scripts/tsconfig.json && tsc --noEmit -p benchmarks/tsconfig.json && tsc --noEmit -p wasm/tsconfig.json && tsc --noEmit -p snowball/tsconfig.json",
|
|
156
163
|
"typecheck": "pnpm run typecheck:src && pnpm run typecheck:tests && pnpm run typecheck:tooling"
|
|
157
164
|
}
|
|
158
165
|
}
|