searchsocket 0.6.0 → 0.6.1
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/cli.js +69 -10
- package/dist/index.cjs +68 -9
- package/dist/index.d.cts +12 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +68 -9
- package/dist/sveltekit.cjs +68 -9
- package/dist/sveltekit.js +68 -9
- package/package.json +10 -11
package/dist/cli.js
CHANGED
|
@@ -12,7 +12,7 @@ import { Command, Option } from "commander";
|
|
|
12
12
|
// package.json
|
|
13
13
|
var package_default = {
|
|
14
14
|
name: "searchsocket",
|
|
15
|
-
version: "0.6.
|
|
15
|
+
version: "0.6.1",
|
|
16
16
|
description: "Semantic site search and MCP retrieval for SvelteKit static sites",
|
|
17
17
|
license: "MIT",
|
|
18
18
|
author: "Greg Priday <greg@siteorigin.com>",
|
|
@@ -874,7 +874,7 @@ var UpstashSearchStore = class {
|
|
|
874
874
|
}
|
|
875
875
|
async upsertChunks(chunks, scope) {
|
|
876
876
|
if (chunks.length === 0) return;
|
|
877
|
-
const BATCH_SIZE =
|
|
877
|
+
const BATCH_SIZE = 90;
|
|
878
878
|
for (let i = 0; i < chunks.length; i += BATCH_SIZE) {
|
|
879
879
|
const batch = chunks.slice(i, i + BATCH_SIZE);
|
|
880
880
|
await this.chunksNs.upsert(
|
|
@@ -1018,7 +1018,7 @@ var UpstashSearchStore = class {
|
|
|
1018
1018
|
}
|
|
1019
1019
|
async deleteByIds(ids, _scope) {
|
|
1020
1020
|
if (ids.length === 0) return;
|
|
1021
|
-
const BATCH_SIZE =
|
|
1021
|
+
const BATCH_SIZE = 90;
|
|
1022
1022
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
1023
1023
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
1024
1024
|
await this.chunksNs.delete(batch);
|
|
@@ -1046,7 +1046,7 @@ var UpstashSearchStore = class {
|
|
|
1046
1046
|
} catch {
|
|
1047
1047
|
}
|
|
1048
1048
|
if (ids.length > 0) {
|
|
1049
|
-
const BATCH_SIZE =
|
|
1049
|
+
const BATCH_SIZE = 90;
|
|
1050
1050
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
1051
1051
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
1052
1052
|
await ns.delete(batch);
|
|
@@ -1085,7 +1085,39 @@ var UpstashSearchStore = class {
|
|
|
1085
1085
|
}));
|
|
1086
1086
|
}
|
|
1087
1087
|
async getContentHashes(scope) {
|
|
1088
|
+
return this.scanHashes(this.chunksNs, scope);
|
|
1089
|
+
}
|
|
1090
|
+
/**
|
|
1091
|
+
* Fetch content hashes for a specific set of chunk keys using direct fetch()
|
|
1092
|
+
* instead of range(). This avoids potential issues with range() returning
|
|
1093
|
+
* vectors from the wrong namespace on hybrid indexes.
|
|
1094
|
+
*/
|
|
1095
|
+
async fetchContentHashesForKeys(keys, scope) {
|
|
1088
1096
|
const map = /* @__PURE__ */ new Map();
|
|
1097
|
+
if (keys.length === 0) return map;
|
|
1098
|
+
const BATCH_SIZE = 90;
|
|
1099
|
+
for (let i = 0; i < keys.length; i += BATCH_SIZE) {
|
|
1100
|
+
const batch = keys.slice(i, i + BATCH_SIZE);
|
|
1101
|
+
try {
|
|
1102
|
+
const results = await this.chunksNs.fetch(batch, {
|
|
1103
|
+
includeMetadata: true
|
|
1104
|
+
});
|
|
1105
|
+
for (const doc of results) {
|
|
1106
|
+
if (doc && doc.metadata?.projectId === scope.projectId && doc.metadata?.scopeName === scope.scopeName && doc.metadata?.contentHash) {
|
|
1107
|
+
map.set(String(doc.id), doc.metadata.contentHash);
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
} catch {
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
return map;
|
|
1114
|
+
}
|
|
1115
|
+
/**
|
|
1116
|
+
* Scan all IDs in the chunks namespace for this scope.
|
|
1117
|
+
* Used for deletion detection (finding stale chunk keys).
|
|
1118
|
+
*/
|
|
1119
|
+
async scanChunkIds(scope) {
|
|
1120
|
+
const ids = /* @__PURE__ */ new Set();
|
|
1089
1121
|
let cursor = "0";
|
|
1090
1122
|
try {
|
|
1091
1123
|
for (; ; ) {
|
|
@@ -1094,6 +1126,28 @@ var UpstashSearchStore = class {
|
|
|
1094
1126
|
limit: 100,
|
|
1095
1127
|
includeMetadata: true
|
|
1096
1128
|
});
|
|
1129
|
+
for (const doc of result.vectors) {
|
|
1130
|
+
if (doc.metadata?.projectId === scope.projectId && doc.metadata?.scopeName === scope.scopeName) {
|
|
1131
|
+
ids.add(String(doc.id));
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1134
|
+
if (!result.nextCursor || result.nextCursor === "0") break;
|
|
1135
|
+
cursor = result.nextCursor;
|
|
1136
|
+
}
|
|
1137
|
+
} catch {
|
|
1138
|
+
}
|
|
1139
|
+
return ids;
|
|
1140
|
+
}
|
|
1141
|
+
async scanHashes(ns, scope) {
|
|
1142
|
+
const map = /* @__PURE__ */ new Map();
|
|
1143
|
+
let cursor = "0";
|
|
1144
|
+
try {
|
|
1145
|
+
for (; ; ) {
|
|
1146
|
+
const result = await ns.range({
|
|
1147
|
+
cursor,
|
|
1148
|
+
limit: 100,
|
|
1149
|
+
includeMetadata: true
|
|
1150
|
+
});
|
|
1097
1151
|
for (const doc of result.vectors) {
|
|
1098
1152
|
if (doc.metadata?.projectId === scope.projectId && doc.metadata?.scopeName === scope.scopeName && doc.metadata?.contentHash) {
|
|
1099
1153
|
map.set(String(doc.id), doc.metadata.contentHash);
|
|
@@ -1156,7 +1210,7 @@ var UpstashSearchStore = class {
|
|
|
1156
1210
|
}
|
|
1157
1211
|
async deletePagesByIds(ids, _scope) {
|
|
1158
1212
|
if (ids.length === 0) return;
|
|
1159
|
-
const BATCH_SIZE =
|
|
1213
|
+
const BATCH_SIZE = 90;
|
|
1160
1214
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
1161
1215
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
1162
1216
|
await this.pagesNs.delete(batch);
|
|
@@ -1164,7 +1218,7 @@ var UpstashSearchStore = class {
|
|
|
1164
1218
|
}
|
|
1165
1219
|
async upsertPages(pages, scope) {
|
|
1166
1220
|
if (pages.length === 0) return;
|
|
1167
|
-
const BATCH_SIZE =
|
|
1221
|
+
const BATCH_SIZE = 90;
|
|
1168
1222
|
for (let i = 0; i < pages.length; i += BATCH_SIZE) {
|
|
1169
1223
|
const batch = pages.slice(i, i + BATCH_SIZE);
|
|
1170
1224
|
await this.pagesNs.upsert(
|
|
@@ -1308,7 +1362,7 @@ var UpstashSearchStore = class {
|
|
|
1308
1362
|
} catch {
|
|
1309
1363
|
}
|
|
1310
1364
|
if (ids.length > 0) {
|
|
1311
|
-
const BATCH_SIZE =
|
|
1365
|
+
const BATCH_SIZE = 90;
|
|
1312
1366
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
1313
1367
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
1314
1368
|
await ns.delete(batch);
|
|
@@ -3375,10 +3429,9 @@ var IndexPipeline = class _IndexPipeline {
|
|
|
3375
3429
|
this.logger.info("Dry run \u2014 no writes will be performed");
|
|
3376
3430
|
}
|
|
3377
3431
|
const manifestStart = stageStart();
|
|
3378
|
-
const existingHashes = options.force ? /* @__PURE__ */ new Map() : await this.store.getContentHashes(scope);
|
|
3379
3432
|
const existingPageHashes = options.force ? /* @__PURE__ */ new Map() : await this.store.getPageHashes(scope);
|
|
3380
3433
|
stageEnd("manifest", manifestStart);
|
|
3381
|
-
this.logger.debug(`Manifest: ${
|
|
3434
|
+
this.logger.debug(`Manifest: ${existingPageHashes.size} existing page hashes loaded`);
|
|
3382
3435
|
const sourceStart = stageStart();
|
|
3383
3436
|
this.logger.info(`Loading pages (source: ${sourceMode})...`);
|
|
3384
3437
|
let sourcePages;
|
|
@@ -3767,6 +3820,11 @@ var IndexPipeline = class _IndexPipeline {
|
|
|
3767
3820
|
for (const chunk of chunks) {
|
|
3768
3821
|
currentChunkMap.set(chunk.chunkKey, chunk);
|
|
3769
3822
|
}
|
|
3823
|
+
const chunkHashStart = stageStart();
|
|
3824
|
+
const currentChunkKeys = chunks.map((c) => c.chunkKey);
|
|
3825
|
+
const existingHashes = options.force ? /* @__PURE__ */ new Map() : await this.store.fetchContentHashesForKeys(currentChunkKeys, scope);
|
|
3826
|
+
stageEnd("chunk_hashes", chunkHashStart);
|
|
3827
|
+
this.logger.debug(`Fetched ${existingHashes.size} existing chunk hashes for ${currentChunkKeys.length} current keys`);
|
|
3770
3828
|
let changedChunks = chunks.filter((chunk) => {
|
|
3771
3829
|
if (options.force) {
|
|
3772
3830
|
return true;
|
|
@@ -3780,7 +3838,8 @@ var IndexPipeline = class _IndexPipeline {
|
|
|
3780
3838
|
}
|
|
3781
3839
|
return existingHash !== chunk.contentHash;
|
|
3782
3840
|
});
|
|
3783
|
-
const
|
|
3841
|
+
const existingChunkIds = options.force ? /* @__PURE__ */ new Set() : await this.store.scanChunkIds(scope);
|
|
3842
|
+
const deletes = [...existingChunkIds].filter((chunkKey) => !currentChunkMap.has(chunkKey));
|
|
3784
3843
|
if (this.hooks.beforeIndex) {
|
|
3785
3844
|
changedChunks = await this.hooks.beforeIndex(changedChunks);
|
|
3786
3845
|
}
|
package/dist/index.cjs
CHANGED
|
@@ -17285,7 +17285,7 @@ var UpstashSearchStore = class {
|
|
|
17285
17285
|
}
|
|
17286
17286
|
async upsertChunks(chunks, scope) {
|
|
17287
17287
|
if (chunks.length === 0) return;
|
|
17288
|
-
const BATCH_SIZE =
|
|
17288
|
+
const BATCH_SIZE = 90;
|
|
17289
17289
|
for (let i = 0; i < chunks.length; i += BATCH_SIZE) {
|
|
17290
17290
|
const batch = chunks.slice(i, i + BATCH_SIZE);
|
|
17291
17291
|
await this.chunksNs.upsert(
|
|
@@ -17429,7 +17429,7 @@ var UpstashSearchStore = class {
|
|
|
17429
17429
|
}
|
|
17430
17430
|
async deleteByIds(ids, _scope) {
|
|
17431
17431
|
if (ids.length === 0) return;
|
|
17432
|
-
const BATCH_SIZE =
|
|
17432
|
+
const BATCH_SIZE = 90;
|
|
17433
17433
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
17434
17434
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
17435
17435
|
await this.chunksNs.delete(batch);
|
|
@@ -17457,7 +17457,7 @@ var UpstashSearchStore = class {
|
|
|
17457
17457
|
} catch {
|
|
17458
17458
|
}
|
|
17459
17459
|
if (ids.length > 0) {
|
|
17460
|
-
const BATCH_SIZE =
|
|
17460
|
+
const BATCH_SIZE = 90;
|
|
17461
17461
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
17462
17462
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
17463
17463
|
await ns.delete(batch);
|
|
@@ -17496,7 +17496,39 @@ var UpstashSearchStore = class {
|
|
|
17496
17496
|
}));
|
|
17497
17497
|
}
|
|
17498
17498
|
async getContentHashes(scope) {
|
|
17499
|
+
return this.scanHashes(this.chunksNs, scope);
|
|
17500
|
+
}
|
|
17501
|
+
/**
|
|
17502
|
+
* Fetch content hashes for a specific set of chunk keys using direct fetch()
|
|
17503
|
+
* instead of range(). This avoids potential issues with range() returning
|
|
17504
|
+
* vectors from the wrong namespace on hybrid indexes.
|
|
17505
|
+
*/
|
|
17506
|
+
async fetchContentHashesForKeys(keys, scope) {
|
|
17499
17507
|
const map = /* @__PURE__ */ new Map();
|
|
17508
|
+
if (keys.length === 0) return map;
|
|
17509
|
+
const BATCH_SIZE = 90;
|
|
17510
|
+
for (let i = 0; i < keys.length; i += BATCH_SIZE) {
|
|
17511
|
+
const batch = keys.slice(i, i + BATCH_SIZE);
|
|
17512
|
+
try {
|
|
17513
|
+
const results = await this.chunksNs.fetch(batch, {
|
|
17514
|
+
includeMetadata: true
|
|
17515
|
+
});
|
|
17516
|
+
for (const doc of results) {
|
|
17517
|
+
if (doc && doc.metadata?.projectId === scope.projectId && doc.metadata?.scopeName === scope.scopeName && doc.metadata?.contentHash) {
|
|
17518
|
+
map.set(String(doc.id), doc.metadata.contentHash);
|
|
17519
|
+
}
|
|
17520
|
+
}
|
|
17521
|
+
} catch {
|
|
17522
|
+
}
|
|
17523
|
+
}
|
|
17524
|
+
return map;
|
|
17525
|
+
}
|
|
17526
|
+
/**
|
|
17527
|
+
* Scan all IDs in the chunks namespace for this scope.
|
|
17528
|
+
* Used for deletion detection (finding stale chunk keys).
|
|
17529
|
+
*/
|
|
17530
|
+
async scanChunkIds(scope) {
|
|
17531
|
+
const ids = /* @__PURE__ */ new Set();
|
|
17500
17532
|
let cursor = "0";
|
|
17501
17533
|
try {
|
|
17502
17534
|
for (; ; ) {
|
|
@@ -17505,6 +17537,28 @@ var UpstashSearchStore = class {
|
|
|
17505
17537
|
limit: 100,
|
|
17506
17538
|
includeMetadata: true
|
|
17507
17539
|
});
|
|
17540
|
+
for (const doc of result.vectors) {
|
|
17541
|
+
if (doc.metadata?.projectId === scope.projectId && doc.metadata?.scopeName === scope.scopeName) {
|
|
17542
|
+
ids.add(String(doc.id));
|
|
17543
|
+
}
|
|
17544
|
+
}
|
|
17545
|
+
if (!result.nextCursor || result.nextCursor === "0") break;
|
|
17546
|
+
cursor = result.nextCursor;
|
|
17547
|
+
}
|
|
17548
|
+
} catch {
|
|
17549
|
+
}
|
|
17550
|
+
return ids;
|
|
17551
|
+
}
|
|
17552
|
+
async scanHashes(ns, scope) {
|
|
17553
|
+
const map = /* @__PURE__ */ new Map();
|
|
17554
|
+
let cursor = "0";
|
|
17555
|
+
try {
|
|
17556
|
+
for (; ; ) {
|
|
17557
|
+
const result = await ns.range({
|
|
17558
|
+
cursor,
|
|
17559
|
+
limit: 100,
|
|
17560
|
+
includeMetadata: true
|
|
17561
|
+
});
|
|
17508
17562
|
for (const doc of result.vectors) {
|
|
17509
17563
|
if (doc.metadata?.projectId === scope.projectId && doc.metadata?.scopeName === scope.scopeName && doc.metadata?.contentHash) {
|
|
17510
17564
|
map.set(String(doc.id), doc.metadata.contentHash);
|
|
@@ -17567,7 +17621,7 @@ var UpstashSearchStore = class {
|
|
|
17567
17621
|
}
|
|
17568
17622
|
async deletePagesByIds(ids, _scope) {
|
|
17569
17623
|
if (ids.length === 0) return;
|
|
17570
|
-
const BATCH_SIZE =
|
|
17624
|
+
const BATCH_SIZE = 90;
|
|
17571
17625
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
17572
17626
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
17573
17627
|
await this.pagesNs.delete(batch);
|
|
@@ -17575,7 +17629,7 @@ var UpstashSearchStore = class {
|
|
|
17575
17629
|
}
|
|
17576
17630
|
async upsertPages(pages, scope) {
|
|
17577
17631
|
if (pages.length === 0) return;
|
|
17578
|
-
const BATCH_SIZE =
|
|
17632
|
+
const BATCH_SIZE = 90;
|
|
17579
17633
|
for (let i = 0; i < pages.length; i += BATCH_SIZE) {
|
|
17580
17634
|
const batch = pages.slice(i, i + BATCH_SIZE);
|
|
17581
17635
|
await this.pagesNs.upsert(
|
|
@@ -17719,7 +17773,7 @@ var UpstashSearchStore = class {
|
|
|
17719
17773
|
} catch {
|
|
17720
17774
|
}
|
|
17721
17775
|
if (ids.length > 0) {
|
|
17722
|
-
const BATCH_SIZE =
|
|
17776
|
+
const BATCH_SIZE = 90;
|
|
17723
17777
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
17724
17778
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
17725
17779
|
await ns.delete(batch);
|
|
@@ -20634,10 +20688,9 @@ var IndexPipeline = class _IndexPipeline {
|
|
|
20634
20688
|
this.logger.info("Dry run \u2014 no writes will be performed");
|
|
20635
20689
|
}
|
|
20636
20690
|
const manifestStart = stageStart();
|
|
20637
|
-
const existingHashes = options.force ? /* @__PURE__ */ new Map() : await this.store.getContentHashes(scope);
|
|
20638
20691
|
const existingPageHashes = options.force ? /* @__PURE__ */ new Map() : await this.store.getPageHashes(scope);
|
|
20639
20692
|
stageEnd("manifest", manifestStart);
|
|
20640
|
-
this.logger.debug(`Manifest: ${
|
|
20693
|
+
this.logger.debug(`Manifest: ${existingPageHashes.size} existing page hashes loaded`);
|
|
20641
20694
|
const sourceStart = stageStart();
|
|
20642
20695
|
this.logger.info(`Loading pages (source: ${sourceMode})...`);
|
|
20643
20696
|
let sourcePages;
|
|
@@ -21026,6 +21079,11 @@ var IndexPipeline = class _IndexPipeline {
|
|
|
21026
21079
|
for (const chunk of chunks) {
|
|
21027
21080
|
currentChunkMap.set(chunk.chunkKey, chunk);
|
|
21028
21081
|
}
|
|
21082
|
+
const chunkHashStart = stageStart();
|
|
21083
|
+
const currentChunkKeys = chunks.map((c) => c.chunkKey);
|
|
21084
|
+
const existingHashes = options.force ? /* @__PURE__ */ new Map() : await this.store.fetchContentHashesForKeys(currentChunkKeys, scope);
|
|
21085
|
+
stageEnd("chunk_hashes", chunkHashStart);
|
|
21086
|
+
this.logger.debug(`Fetched ${existingHashes.size} existing chunk hashes for ${currentChunkKeys.length} current keys`);
|
|
21029
21087
|
let changedChunks = chunks.filter((chunk) => {
|
|
21030
21088
|
if (options.force) {
|
|
21031
21089
|
return true;
|
|
@@ -21039,7 +21097,8 @@ var IndexPipeline = class _IndexPipeline {
|
|
|
21039
21097
|
}
|
|
21040
21098
|
return existingHash !== chunk.contentHash;
|
|
21041
21099
|
});
|
|
21042
|
-
const
|
|
21100
|
+
const existingChunkIds = options.force ? /* @__PURE__ */ new Set() : await this.store.scanChunkIds(scope);
|
|
21101
|
+
const deletes = [...existingChunkIds].filter((chunkKey) => !currentChunkMap.has(chunkKey));
|
|
21043
21102
|
if (this.hooks.beforeIndex) {
|
|
21044
21103
|
changedChunks = await this.hooks.beforeIndex(changedChunks);
|
|
21045
21104
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -88,6 +88,18 @@ declare class UpstashSearchStore {
|
|
|
88
88
|
deleteScope(scope: Scope): Promise<void>;
|
|
89
89
|
listScopes(projectId: string): Promise<ScopeInfo[]>;
|
|
90
90
|
getContentHashes(scope: Scope): Promise<Map<string, string>>;
|
|
91
|
+
/**
|
|
92
|
+
* Fetch content hashes for a specific set of chunk keys using direct fetch()
|
|
93
|
+
* instead of range(). This avoids potential issues with range() returning
|
|
94
|
+
* vectors from the wrong namespace on hybrid indexes.
|
|
95
|
+
*/
|
|
96
|
+
fetchContentHashesForKeys(keys: string[], scope: Scope): Promise<Map<string, string>>;
|
|
97
|
+
/**
|
|
98
|
+
* Scan all IDs in the chunks namespace for this scope.
|
|
99
|
+
* Used for deletion detection (finding stale chunk keys).
|
|
100
|
+
*/
|
|
101
|
+
scanChunkIds(scope: Scope): Promise<Set<string>>;
|
|
102
|
+
private scanHashes;
|
|
91
103
|
listPages(scope: Scope, opts?: {
|
|
92
104
|
cursor?: string;
|
|
93
105
|
limit?: number;
|
package/dist/index.d.ts
CHANGED
|
@@ -88,6 +88,18 @@ declare class UpstashSearchStore {
|
|
|
88
88
|
deleteScope(scope: Scope): Promise<void>;
|
|
89
89
|
listScopes(projectId: string): Promise<ScopeInfo[]>;
|
|
90
90
|
getContentHashes(scope: Scope): Promise<Map<string, string>>;
|
|
91
|
+
/**
|
|
92
|
+
* Fetch content hashes for a specific set of chunk keys using direct fetch()
|
|
93
|
+
* instead of range(). This avoids potential issues with range() returning
|
|
94
|
+
* vectors from the wrong namespace on hybrid indexes.
|
|
95
|
+
*/
|
|
96
|
+
fetchContentHashesForKeys(keys: string[], scope: Scope): Promise<Map<string, string>>;
|
|
97
|
+
/**
|
|
98
|
+
* Scan all IDs in the chunks namespace for this scope.
|
|
99
|
+
* Used for deletion detection (finding stale chunk keys).
|
|
100
|
+
*/
|
|
101
|
+
scanChunkIds(scope: Scope): Promise<Set<string>>;
|
|
102
|
+
private scanHashes;
|
|
91
103
|
listPages(scope: Scope, opts?: {
|
|
92
104
|
cursor?: string;
|
|
93
105
|
limit?: number;
|
package/dist/index.js
CHANGED
|
@@ -17273,7 +17273,7 @@ var UpstashSearchStore = class {
|
|
|
17273
17273
|
}
|
|
17274
17274
|
async upsertChunks(chunks, scope) {
|
|
17275
17275
|
if (chunks.length === 0) return;
|
|
17276
|
-
const BATCH_SIZE =
|
|
17276
|
+
const BATCH_SIZE = 90;
|
|
17277
17277
|
for (let i = 0; i < chunks.length; i += BATCH_SIZE) {
|
|
17278
17278
|
const batch = chunks.slice(i, i + BATCH_SIZE);
|
|
17279
17279
|
await this.chunksNs.upsert(
|
|
@@ -17417,7 +17417,7 @@ var UpstashSearchStore = class {
|
|
|
17417
17417
|
}
|
|
17418
17418
|
async deleteByIds(ids, _scope) {
|
|
17419
17419
|
if (ids.length === 0) return;
|
|
17420
|
-
const BATCH_SIZE =
|
|
17420
|
+
const BATCH_SIZE = 90;
|
|
17421
17421
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
17422
17422
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
17423
17423
|
await this.chunksNs.delete(batch);
|
|
@@ -17445,7 +17445,7 @@ var UpstashSearchStore = class {
|
|
|
17445
17445
|
} catch {
|
|
17446
17446
|
}
|
|
17447
17447
|
if (ids.length > 0) {
|
|
17448
|
-
const BATCH_SIZE =
|
|
17448
|
+
const BATCH_SIZE = 90;
|
|
17449
17449
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
17450
17450
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
17451
17451
|
await ns.delete(batch);
|
|
@@ -17484,7 +17484,39 @@ var UpstashSearchStore = class {
|
|
|
17484
17484
|
}));
|
|
17485
17485
|
}
|
|
17486
17486
|
async getContentHashes(scope) {
|
|
17487
|
+
return this.scanHashes(this.chunksNs, scope);
|
|
17488
|
+
}
|
|
17489
|
+
/**
|
|
17490
|
+
* Fetch content hashes for a specific set of chunk keys using direct fetch()
|
|
17491
|
+
* instead of range(). This avoids potential issues with range() returning
|
|
17492
|
+
* vectors from the wrong namespace on hybrid indexes.
|
|
17493
|
+
*/
|
|
17494
|
+
async fetchContentHashesForKeys(keys, scope) {
|
|
17487
17495
|
const map = /* @__PURE__ */ new Map();
|
|
17496
|
+
if (keys.length === 0) return map;
|
|
17497
|
+
const BATCH_SIZE = 90;
|
|
17498
|
+
for (let i = 0; i < keys.length; i += BATCH_SIZE) {
|
|
17499
|
+
const batch = keys.slice(i, i + BATCH_SIZE);
|
|
17500
|
+
try {
|
|
17501
|
+
const results = await this.chunksNs.fetch(batch, {
|
|
17502
|
+
includeMetadata: true
|
|
17503
|
+
});
|
|
17504
|
+
for (const doc of results) {
|
|
17505
|
+
if (doc && doc.metadata?.projectId === scope.projectId && doc.metadata?.scopeName === scope.scopeName && doc.metadata?.contentHash) {
|
|
17506
|
+
map.set(String(doc.id), doc.metadata.contentHash);
|
|
17507
|
+
}
|
|
17508
|
+
}
|
|
17509
|
+
} catch {
|
|
17510
|
+
}
|
|
17511
|
+
}
|
|
17512
|
+
return map;
|
|
17513
|
+
}
|
|
17514
|
+
/**
|
|
17515
|
+
* Scan all IDs in the chunks namespace for this scope.
|
|
17516
|
+
* Used for deletion detection (finding stale chunk keys).
|
|
17517
|
+
*/
|
|
17518
|
+
async scanChunkIds(scope) {
|
|
17519
|
+
const ids = /* @__PURE__ */ new Set();
|
|
17488
17520
|
let cursor = "0";
|
|
17489
17521
|
try {
|
|
17490
17522
|
for (; ; ) {
|
|
@@ -17493,6 +17525,28 @@ var UpstashSearchStore = class {
|
|
|
17493
17525
|
limit: 100,
|
|
17494
17526
|
includeMetadata: true
|
|
17495
17527
|
});
|
|
17528
|
+
for (const doc of result.vectors) {
|
|
17529
|
+
if (doc.metadata?.projectId === scope.projectId && doc.metadata?.scopeName === scope.scopeName) {
|
|
17530
|
+
ids.add(String(doc.id));
|
|
17531
|
+
}
|
|
17532
|
+
}
|
|
17533
|
+
if (!result.nextCursor || result.nextCursor === "0") break;
|
|
17534
|
+
cursor = result.nextCursor;
|
|
17535
|
+
}
|
|
17536
|
+
} catch {
|
|
17537
|
+
}
|
|
17538
|
+
return ids;
|
|
17539
|
+
}
|
|
17540
|
+
async scanHashes(ns, scope) {
|
|
17541
|
+
const map = /* @__PURE__ */ new Map();
|
|
17542
|
+
let cursor = "0";
|
|
17543
|
+
try {
|
|
17544
|
+
for (; ; ) {
|
|
17545
|
+
const result = await ns.range({
|
|
17546
|
+
cursor,
|
|
17547
|
+
limit: 100,
|
|
17548
|
+
includeMetadata: true
|
|
17549
|
+
});
|
|
17496
17550
|
for (const doc of result.vectors) {
|
|
17497
17551
|
if (doc.metadata?.projectId === scope.projectId && doc.metadata?.scopeName === scope.scopeName && doc.metadata?.contentHash) {
|
|
17498
17552
|
map.set(String(doc.id), doc.metadata.contentHash);
|
|
@@ -17555,7 +17609,7 @@ var UpstashSearchStore = class {
|
|
|
17555
17609
|
}
|
|
17556
17610
|
async deletePagesByIds(ids, _scope) {
|
|
17557
17611
|
if (ids.length === 0) return;
|
|
17558
|
-
const BATCH_SIZE =
|
|
17612
|
+
const BATCH_SIZE = 90;
|
|
17559
17613
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
17560
17614
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
17561
17615
|
await this.pagesNs.delete(batch);
|
|
@@ -17563,7 +17617,7 @@ var UpstashSearchStore = class {
|
|
|
17563
17617
|
}
|
|
17564
17618
|
async upsertPages(pages, scope) {
|
|
17565
17619
|
if (pages.length === 0) return;
|
|
17566
|
-
const BATCH_SIZE =
|
|
17620
|
+
const BATCH_SIZE = 90;
|
|
17567
17621
|
for (let i = 0; i < pages.length; i += BATCH_SIZE) {
|
|
17568
17622
|
const batch = pages.slice(i, i + BATCH_SIZE);
|
|
17569
17623
|
await this.pagesNs.upsert(
|
|
@@ -17707,7 +17761,7 @@ var UpstashSearchStore = class {
|
|
|
17707
17761
|
} catch {
|
|
17708
17762
|
}
|
|
17709
17763
|
if (ids.length > 0) {
|
|
17710
|
-
const BATCH_SIZE =
|
|
17764
|
+
const BATCH_SIZE = 90;
|
|
17711
17765
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
17712
17766
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
17713
17767
|
await ns.delete(batch);
|
|
@@ -20622,10 +20676,9 @@ var IndexPipeline = class _IndexPipeline {
|
|
|
20622
20676
|
this.logger.info("Dry run \u2014 no writes will be performed");
|
|
20623
20677
|
}
|
|
20624
20678
|
const manifestStart = stageStart();
|
|
20625
|
-
const existingHashes = options.force ? /* @__PURE__ */ new Map() : await this.store.getContentHashes(scope);
|
|
20626
20679
|
const existingPageHashes = options.force ? /* @__PURE__ */ new Map() : await this.store.getPageHashes(scope);
|
|
20627
20680
|
stageEnd("manifest", manifestStart);
|
|
20628
|
-
this.logger.debug(`Manifest: ${
|
|
20681
|
+
this.logger.debug(`Manifest: ${existingPageHashes.size} existing page hashes loaded`);
|
|
20629
20682
|
const sourceStart = stageStart();
|
|
20630
20683
|
this.logger.info(`Loading pages (source: ${sourceMode})...`);
|
|
20631
20684
|
let sourcePages;
|
|
@@ -21014,6 +21067,11 @@ var IndexPipeline = class _IndexPipeline {
|
|
|
21014
21067
|
for (const chunk of chunks) {
|
|
21015
21068
|
currentChunkMap.set(chunk.chunkKey, chunk);
|
|
21016
21069
|
}
|
|
21070
|
+
const chunkHashStart = stageStart();
|
|
21071
|
+
const currentChunkKeys = chunks.map((c) => c.chunkKey);
|
|
21072
|
+
const existingHashes = options.force ? /* @__PURE__ */ new Map() : await this.store.fetchContentHashesForKeys(currentChunkKeys, scope);
|
|
21073
|
+
stageEnd("chunk_hashes", chunkHashStart);
|
|
21074
|
+
this.logger.debug(`Fetched ${existingHashes.size} existing chunk hashes for ${currentChunkKeys.length} current keys`);
|
|
21017
21075
|
let changedChunks = chunks.filter((chunk) => {
|
|
21018
21076
|
if (options.force) {
|
|
21019
21077
|
return true;
|
|
@@ -21027,7 +21085,8 @@ var IndexPipeline = class _IndexPipeline {
|
|
|
21027
21085
|
}
|
|
21028
21086
|
return existingHash !== chunk.contentHash;
|
|
21029
21087
|
});
|
|
21030
|
-
const
|
|
21088
|
+
const existingChunkIds = options.force ? /* @__PURE__ */ new Set() : await this.store.scanChunkIds(scope);
|
|
21089
|
+
const deletes = [...existingChunkIds].filter((chunkKey) => !currentChunkMap.has(chunkKey));
|
|
21031
21090
|
if (this.hooks.beforeIndex) {
|
|
21032
21091
|
changedChunks = await this.hooks.beforeIndex(changedChunks);
|
|
21033
21092
|
}
|
package/dist/sveltekit.cjs
CHANGED
|
@@ -17316,7 +17316,7 @@ var UpstashSearchStore = class {
|
|
|
17316
17316
|
}
|
|
17317
17317
|
async upsertChunks(chunks, scope) {
|
|
17318
17318
|
if (chunks.length === 0) return;
|
|
17319
|
-
const BATCH_SIZE =
|
|
17319
|
+
const BATCH_SIZE = 90;
|
|
17320
17320
|
for (let i = 0; i < chunks.length; i += BATCH_SIZE) {
|
|
17321
17321
|
const batch = chunks.slice(i, i + BATCH_SIZE);
|
|
17322
17322
|
await this.chunksNs.upsert(
|
|
@@ -17460,7 +17460,7 @@ var UpstashSearchStore = class {
|
|
|
17460
17460
|
}
|
|
17461
17461
|
async deleteByIds(ids, _scope) {
|
|
17462
17462
|
if (ids.length === 0) return;
|
|
17463
|
-
const BATCH_SIZE =
|
|
17463
|
+
const BATCH_SIZE = 90;
|
|
17464
17464
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
17465
17465
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
17466
17466
|
await this.chunksNs.delete(batch);
|
|
@@ -17488,7 +17488,7 @@ var UpstashSearchStore = class {
|
|
|
17488
17488
|
} catch {
|
|
17489
17489
|
}
|
|
17490
17490
|
if (ids.length > 0) {
|
|
17491
|
-
const BATCH_SIZE =
|
|
17491
|
+
const BATCH_SIZE = 90;
|
|
17492
17492
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
17493
17493
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
17494
17494
|
await ns.delete(batch);
|
|
@@ -17527,7 +17527,39 @@ var UpstashSearchStore = class {
|
|
|
17527
17527
|
}));
|
|
17528
17528
|
}
|
|
17529
17529
|
async getContentHashes(scope) {
|
|
17530
|
+
return this.scanHashes(this.chunksNs, scope);
|
|
17531
|
+
}
|
|
17532
|
+
/**
|
|
17533
|
+
* Fetch content hashes for a specific set of chunk keys using direct fetch()
|
|
17534
|
+
* instead of range(). This avoids potential issues with range() returning
|
|
17535
|
+
* vectors from the wrong namespace on hybrid indexes.
|
|
17536
|
+
*/
|
|
17537
|
+
async fetchContentHashesForKeys(keys, scope) {
|
|
17530
17538
|
const map = /* @__PURE__ */ new Map();
|
|
17539
|
+
if (keys.length === 0) return map;
|
|
17540
|
+
const BATCH_SIZE = 90;
|
|
17541
|
+
for (let i = 0; i < keys.length; i += BATCH_SIZE) {
|
|
17542
|
+
const batch = keys.slice(i, i + BATCH_SIZE);
|
|
17543
|
+
try {
|
|
17544
|
+
const results = await this.chunksNs.fetch(batch, {
|
|
17545
|
+
includeMetadata: true
|
|
17546
|
+
});
|
|
17547
|
+
for (const doc of results) {
|
|
17548
|
+
if (doc && doc.metadata?.projectId === scope.projectId && doc.metadata?.scopeName === scope.scopeName && doc.metadata?.contentHash) {
|
|
17549
|
+
map.set(String(doc.id), doc.metadata.contentHash);
|
|
17550
|
+
}
|
|
17551
|
+
}
|
|
17552
|
+
} catch {
|
|
17553
|
+
}
|
|
17554
|
+
}
|
|
17555
|
+
return map;
|
|
17556
|
+
}
|
|
17557
|
+
/**
|
|
17558
|
+
* Scan all IDs in the chunks namespace for this scope.
|
|
17559
|
+
* Used for deletion detection (finding stale chunk keys).
|
|
17560
|
+
*/
|
|
17561
|
+
async scanChunkIds(scope) {
|
|
17562
|
+
const ids = /* @__PURE__ */ new Set();
|
|
17531
17563
|
let cursor = "0";
|
|
17532
17564
|
try {
|
|
17533
17565
|
for (; ; ) {
|
|
@@ -17536,6 +17568,28 @@ var UpstashSearchStore = class {
|
|
|
17536
17568
|
limit: 100,
|
|
17537
17569
|
includeMetadata: true
|
|
17538
17570
|
});
|
|
17571
|
+
for (const doc of result.vectors) {
|
|
17572
|
+
if (doc.metadata?.projectId === scope.projectId && doc.metadata?.scopeName === scope.scopeName) {
|
|
17573
|
+
ids.add(String(doc.id));
|
|
17574
|
+
}
|
|
17575
|
+
}
|
|
17576
|
+
if (!result.nextCursor || result.nextCursor === "0") break;
|
|
17577
|
+
cursor = result.nextCursor;
|
|
17578
|
+
}
|
|
17579
|
+
} catch {
|
|
17580
|
+
}
|
|
17581
|
+
return ids;
|
|
17582
|
+
}
|
|
17583
|
+
async scanHashes(ns, scope) {
|
|
17584
|
+
const map = /* @__PURE__ */ new Map();
|
|
17585
|
+
let cursor = "0";
|
|
17586
|
+
try {
|
|
17587
|
+
for (; ; ) {
|
|
17588
|
+
const result = await ns.range({
|
|
17589
|
+
cursor,
|
|
17590
|
+
limit: 100,
|
|
17591
|
+
includeMetadata: true
|
|
17592
|
+
});
|
|
17539
17593
|
for (const doc of result.vectors) {
|
|
17540
17594
|
if (doc.metadata?.projectId === scope.projectId && doc.metadata?.scopeName === scope.scopeName && doc.metadata?.contentHash) {
|
|
17541
17595
|
map.set(String(doc.id), doc.metadata.contentHash);
|
|
@@ -17598,7 +17652,7 @@ var UpstashSearchStore = class {
|
|
|
17598
17652
|
}
|
|
17599
17653
|
async deletePagesByIds(ids, _scope) {
|
|
17600
17654
|
if (ids.length === 0) return;
|
|
17601
|
-
const BATCH_SIZE =
|
|
17655
|
+
const BATCH_SIZE = 90;
|
|
17602
17656
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
17603
17657
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
17604
17658
|
await this.pagesNs.delete(batch);
|
|
@@ -17606,7 +17660,7 @@ var UpstashSearchStore = class {
|
|
|
17606
17660
|
}
|
|
17607
17661
|
async upsertPages(pages, scope) {
|
|
17608
17662
|
if (pages.length === 0) return;
|
|
17609
|
-
const BATCH_SIZE =
|
|
17663
|
+
const BATCH_SIZE = 90;
|
|
17610
17664
|
for (let i = 0; i < pages.length; i += BATCH_SIZE) {
|
|
17611
17665
|
const batch = pages.slice(i, i + BATCH_SIZE);
|
|
17612
17666
|
await this.pagesNs.upsert(
|
|
@@ -17750,7 +17804,7 @@ var UpstashSearchStore = class {
|
|
|
17750
17804
|
} catch {
|
|
17751
17805
|
}
|
|
17752
17806
|
if (ids.length > 0) {
|
|
17753
|
-
const BATCH_SIZE =
|
|
17807
|
+
const BATCH_SIZE = 90;
|
|
17754
17808
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
17755
17809
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
17756
17810
|
await ns.delete(batch);
|
|
@@ -21776,10 +21830,9 @@ var IndexPipeline = class _IndexPipeline {
|
|
|
21776
21830
|
this.logger.info("Dry run \u2014 no writes will be performed");
|
|
21777
21831
|
}
|
|
21778
21832
|
const manifestStart = stageStart();
|
|
21779
|
-
const existingHashes = options.force ? /* @__PURE__ */ new Map() : await this.store.getContentHashes(scope);
|
|
21780
21833
|
const existingPageHashes = options.force ? /* @__PURE__ */ new Map() : await this.store.getPageHashes(scope);
|
|
21781
21834
|
stageEnd("manifest", manifestStart);
|
|
21782
|
-
this.logger.debug(`Manifest: ${
|
|
21835
|
+
this.logger.debug(`Manifest: ${existingPageHashes.size} existing page hashes loaded`);
|
|
21783
21836
|
const sourceStart = stageStart();
|
|
21784
21837
|
this.logger.info(`Loading pages (source: ${sourceMode})...`);
|
|
21785
21838
|
let sourcePages;
|
|
@@ -22168,6 +22221,11 @@ var IndexPipeline = class _IndexPipeline {
|
|
|
22168
22221
|
for (const chunk of chunks) {
|
|
22169
22222
|
currentChunkMap.set(chunk.chunkKey, chunk);
|
|
22170
22223
|
}
|
|
22224
|
+
const chunkHashStart = stageStart();
|
|
22225
|
+
const currentChunkKeys = chunks.map((c) => c.chunkKey);
|
|
22226
|
+
const existingHashes = options.force ? /* @__PURE__ */ new Map() : await this.store.fetchContentHashesForKeys(currentChunkKeys, scope);
|
|
22227
|
+
stageEnd("chunk_hashes", chunkHashStart);
|
|
22228
|
+
this.logger.debug(`Fetched ${existingHashes.size} existing chunk hashes for ${currentChunkKeys.length} current keys`);
|
|
22171
22229
|
let changedChunks = chunks.filter((chunk) => {
|
|
22172
22230
|
if (options.force) {
|
|
22173
22231
|
return true;
|
|
@@ -22181,7 +22239,8 @@ var IndexPipeline = class _IndexPipeline {
|
|
|
22181
22239
|
}
|
|
22182
22240
|
return existingHash !== chunk.contentHash;
|
|
22183
22241
|
});
|
|
22184
|
-
const
|
|
22242
|
+
const existingChunkIds = options.force ? /* @__PURE__ */ new Set() : await this.store.scanChunkIds(scope);
|
|
22243
|
+
const deletes = [...existingChunkIds].filter((chunkKey) => !currentChunkMap.has(chunkKey));
|
|
22185
22244
|
if (this.hooks.beforeIndex) {
|
|
22186
22245
|
changedChunks = await this.hooks.beforeIndex(changedChunks);
|
|
22187
22246
|
}
|
package/dist/sveltekit.js
CHANGED
|
@@ -17304,7 +17304,7 @@ var UpstashSearchStore = class {
|
|
|
17304
17304
|
}
|
|
17305
17305
|
async upsertChunks(chunks, scope) {
|
|
17306
17306
|
if (chunks.length === 0) return;
|
|
17307
|
-
const BATCH_SIZE =
|
|
17307
|
+
const BATCH_SIZE = 90;
|
|
17308
17308
|
for (let i = 0; i < chunks.length; i += BATCH_SIZE) {
|
|
17309
17309
|
const batch = chunks.slice(i, i + BATCH_SIZE);
|
|
17310
17310
|
await this.chunksNs.upsert(
|
|
@@ -17448,7 +17448,7 @@ var UpstashSearchStore = class {
|
|
|
17448
17448
|
}
|
|
17449
17449
|
async deleteByIds(ids, _scope) {
|
|
17450
17450
|
if (ids.length === 0) return;
|
|
17451
|
-
const BATCH_SIZE =
|
|
17451
|
+
const BATCH_SIZE = 90;
|
|
17452
17452
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
17453
17453
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
17454
17454
|
await this.chunksNs.delete(batch);
|
|
@@ -17476,7 +17476,7 @@ var UpstashSearchStore = class {
|
|
|
17476
17476
|
} catch {
|
|
17477
17477
|
}
|
|
17478
17478
|
if (ids.length > 0) {
|
|
17479
|
-
const BATCH_SIZE =
|
|
17479
|
+
const BATCH_SIZE = 90;
|
|
17480
17480
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
17481
17481
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
17482
17482
|
await ns.delete(batch);
|
|
@@ -17515,7 +17515,39 @@ var UpstashSearchStore = class {
|
|
|
17515
17515
|
}));
|
|
17516
17516
|
}
|
|
17517
17517
|
async getContentHashes(scope) {
|
|
17518
|
+
return this.scanHashes(this.chunksNs, scope);
|
|
17519
|
+
}
|
|
17520
|
+
/**
|
|
17521
|
+
* Fetch content hashes for a specific set of chunk keys using direct fetch()
|
|
17522
|
+
* instead of range(). This avoids potential issues with range() returning
|
|
17523
|
+
* vectors from the wrong namespace on hybrid indexes.
|
|
17524
|
+
*/
|
|
17525
|
+
async fetchContentHashesForKeys(keys, scope) {
|
|
17518
17526
|
const map = /* @__PURE__ */ new Map();
|
|
17527
|
+
if (keys.length === 0) return map;
|
|
17528
|
+
const BATCH_SIZE = 90;
|
|
17529
|
+
for (let i = 0; i < keys.length; i += BATCH_SIZE) {
|
|
17530
|
+
const batch = keys.slice(i, i + BATCH_SIZE);
|
|
17531
|
+
try {
|
|
17532
|
+
const results = await this.chunksNs.fetch(batch, {
|
|
17533
|
+
includeMetadata: true
|
|
17534
|
+
});
|
|
17535
|
+
for (const doc of results) {
|
|
17536
|
+
if (doc && doc.metadata?.projectId === scope.projectId && doc.metadata?.scopeName === scope.scopeName && doc.metadata?.contentHash) {
|
|
17537
|
+
map.set(String(doc.id), doc.metadata.contentHash);
|
|
17538
|
+
}
|
|
17539
|
+
}
|
|
17540
|
+
} catch {
|
|
17541
|
+
}
|
|
17542
|
+
}
|
|
17543
|
+
return map;
|
|
17544
|
+
}
|
|
17545
|
+
/**
|
|
17546
|
+
* Scan all IDs in the chunks namespace for this scope.
|
|
17547
|
+
* Used for deletion detection (finding stale chunk keys).
|
|
17548
|
+
*/
|
|
17549
|
+
async scanChunkIds(scope) {
|
|
17550
|
+
const ids = /* @__PURE__ */ new Set();
|
|
17519
17551
|
let cursor = "0";
|
|
17520
17552
|
try {
|
|
17521
17553
|
for (; ; ) {
|
|
@@ -17524,6 +17556,28 @@ var UpstashSearchStore = class {
|
|
|
17524
17556
|
limit: 100,
|
|
17525
17557
|
includeMetadata: true
|
|
17526
17558
|
});
|
|
17559
|
+
for (const doc of result.vectors) {
|
|
17560
|
+
if (doc.metadata?.projectId === scope.projectId && doc.metadata?.scopeName === scope.scopeName) {
|
|
17561
|
+
ids.add(String(doc.id));
|
|
17562
|
+
}
|
|
17563
|
+
}
|
|
17564
|
+
if (!result.nextCursor || result.nextCursor === "0") break;
|
|
17565
|
+
cursor = result.nextCursor;
|
|
17566
|
+
}
|
|
17567
|
+
} catch {
|
|
17568
|
+
}
|
|
17569
|
+
return ids;
|
|
17570
|
+
}
|
|
17571
|
+
async scanHashes(ns, scope) {
|
|
17572
|
+
const map = /* @__PURE__ */ new Map();
|
|
17573
|
+
let cursor = "0";
|
|
17574
|
+
try {
|
|
17575
|
+
for (; ; ) {
|
|
17576
|
+
const result = await ns.range({
|
|
17577
|
+
cursor,
|
|
17578
|
+
limit: 100,
|
|
17579
|
+
includeMetadata: true
|
|
17580
|
+
});
|
|
17527
17581
|
for (const doc of result.vectors) {
|
|
17528
17582
|
if (doc.metadata?.projectId === scope.projectId && doc.metadata?.scopeName === scope.scopeName && doc.metadata?.contentHash) {
|
|
17529
17583
|
map.set(String(doc.id), doc.metadata.contentHash);
|
|
@@ -17586,7 +17640,7 @@ var UpstashSearchStore = class {
|
|
|
17586
17640
|
}
|
|
17587
17641
|
async deletePagesByIds(ids, _scope) {
|
|
17588
17642
|
if (ids.length === 0) return;
|
|
17589
|
-
const BATCH_SIZE =
|
|
17643
|
+
const BATCH_SIZE = 90;
|
|
17590
17644
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
17591
17645
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
17592
17646
|
await this.pagesNs.delete(batch);
|
|
@@ -17594,7 +17648,7 @@ var UpstashSearchStore = class {
|
|
|
17594
17648
|
}
|
|
17595
17649
|
async upsertPages(pages, scope) {
|
|
17596
17650
|
if (pages.length === 0) return;
|
|
17597
|
-
const BATCH_SIZE =
|
|
17651
|
+
const BATCH_SIZE = 90;
|
|
17598
17652
|
for (let i = 0; i < pages.length; i += BATCH_SIZE) {
|
|
17599
17653
|
const batch = pages.slice(i, i + BATCH_SIZE);
|
|
17600
17654
|
await this.pagesNs.upsert(
|
|
@@ -17738,7 +17792,7 @@ var UpstashSearchStore = class {
|
|
|
17738
17792
|
} catch {
|
|
17739
17793
|
}
|
|
17740
17794
|
if (ids.length > 0) {
|
|
17741
|
-
const BATCH_SIZE =
|
|
17795
|
+
const BATCH_SIZE = 90;
|
|
17742
17796
|
for (let i = 0; i < ids.length; i += BATCH_SIZE) {
|
|
17743
17797
|
const batch = ids.slice(i, i + BATCH_SIZE);
|
|
17744
17798
|
await ns.delete(batch);
|
|
@@ -21764,10 +21818,9 @@ var IndexPipeline = class _IndexPipeline {
|
|
|
21764
21818
|
this.logger.info("Dry run \u2014 no writes will be performed");
|
|
21765
21819
|
}
|
|
21766
21820
|
const manifestStart = stageStart();
|
|
21767
|
-
const existingHashes = options.force ? /* @__PURE__ */ new Map() : await this.store.getContentHashes(scope);
|
|
21768
21821
|
const existingPageHashes = options.force ? /* @__PURE__ */ new Map() : await this.store.getPageHashes(scope);
|
|
21769
21822
|
stageEnd("manifest", manifestStart);
|
|
21770
|
-
this.logger.debug(`Manifest: ${
|
|
21823
|
+
this.logger.debug(`Manifest: ${existingPageHashes.size} existing page hashes loaded`);
|
|
21771
21824
|
const sourceStart = stageStart();
|
|
21772
21825
|
this.logger.info(`Loading pages (source: ${sourceMode})...`);
|
|
21773
21826
|
let sourcePages;
|
|
@@ -22156,6 +22209,11 @@ var IndexPipeline = class _IndexPipeline {
|
|
|
22156
22209
|
for (const chunk of chunks) {
|
|
22157
22210
|
currentChunkMap.set(chunk.chunkKey, chunk);
|
|
22158
22211
|
}
|
|
22212
|
+
const chunkHashStart = stageStart();
|
|
22213
|
+
const currentChunkKeys = chunks.map((c) => c.chunkKey);
|
|
22214
|
+
const existingHashes = options.force ? /* @__PURE__ */ new Map() : await this.store.fetchContentHashesForKeys(currentChunkKeys, scope);
|
|
22215
|
+
stageEnd("chunk_hashes", chunkHashStart);
|
|
22216
|
+
this.logger.debug(`Fetched ${existingHashes.size} existing chunk hashes for ${currentChunkKeys.length} current keys`);
|
|
22159
22217
|
let changedChunks = chunks.filter((chunk) => {
|
|
22160
22218
|
if (options.force) {
|
|
22161
22219
|
return true;
|
|
@@ -22169,7 +22227,8 @@ var IndexPipeline = class _IndexPipeline {
|
|
|
22169
22227
|
}
|
|
22170
22228
|
return existingHash !== chunk.contentHash;
|
|
22171
22229
|
});
|
|
22172
|
-
const
|
|
22230
|
+
const existingChunkIds = options.force ? /* @__PURE__ */ new Set() : await this.store.scanChunkIds(scope);
|
|
22231
|
+
const deletes = [...existingChunkIds].filter((chunkKey) => !currentChunkMap.has(chunkKey));
|
|
22173
22232
|
if (this.hooks.beforeIndex) {
|
|
22174
22233
|
changedChunks = await this.hooks.beforeIndex(changedChunks);
|
|
22175
22234
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "searchsocket",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.1",
|
|
4
4
|
"description": "Semantic site search and MCP retrieval for SvelteKit static sites",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Greg Priday <greg@siteorigin.com>",
|
|
@@ -67,18 +67,9 @@
|
|
|
67
67
|
"optional": true
|
|
68
68
|
}
|
|
69
69
|
},
|
|
70
|
-
"scripts": {
|
|
71
|
-
"build": "tsup",
|
|
72
|
-
"clean": "rm -rf dist",
|
|
73
|
-
"typecheck": "tsc --noEmit",
|
|
74
|
-
"test": "vitest run",
|
|
75
|
-
"test:watch": "vitest",
|
|
76
|
-
"test:quality": "SEARCHSOCKET_QUALITY_TESTS=1 vitest run tests/quality.test.ts"
|
|
77
|
-
},
|
|
78
70
|
"engines": {
|
|
79
71
|
"node": ">=20"
|
|
80
72
|
},
|
|
81
|
-
"packageManager": "pnpm@10.29.2",
|
|
82
73
|
"dependencies": {
|
|
83
74
|
"@clack/prompts": "^1.2.0",
|
|
84
75
|
"@modelcontextprotocol/sdk": "^1.26.0",
|
|
@@ -107,5 +98,13 @@
|
|
|
107
98
|
"tsup": "^8.5.1",
|
|
108
99
|
"typescript": "^5.9.3",
|
|
109
100
|
"vitest": "^4.0.18"
|
|
101
|
+
},
|
|
102
|
+
"scripts": {
|
|
103
|
+
"build": "tsup",
|
|
104
|
+
"clean": "rm -rf dist",
|
|
105
|
+
"typecheck": "tsc --noEmit",
|
|
106
|
+
"test": "vitest run",
|
|
107
|
+
"test:watch": "vitest",
|
|
108
|
+
"test:quality": "SEARCHSOCKET_QUALITY_TESTS=1 vitest run tests/quality.test.ts"
|
|
110
109
|
}
|
|
111
|
-
}
|
|
110
|
+
}
|