refactor(search): use typed OpenSearch SDK request body
Some checks failed
CI / check (push) Failing after 1m0s

Pull in @opensearch-project/opensearch only for its
Search_RequestBody type so the inline search body is
type-checked. Also drops the unsupported
highlight.content.boundary_scanner_locale option.
This commit is contained in:
Julien Calixte
2026-06-07 12:04:43 +02:00
parent 4ff3ea6644
commit 7875d24d48
3 changed files with 42 additions and 7 deletions

View File

@@ -18,6 +18,7 @@
"imports": { "imports": {
"@db/sqlite": "jsr:@db/sqlite@^0.13.0", "@db/sqlite": "jsr:@db/sqlite@^0.13.0",
"@oak/oak": "jsr:@oak/oak@^17.2.0", "@oak/oak": "jsr:@oak/oak@^17.2.0",
"@opensearch-project/opensearch": "npm:@opensearch-project/opensearch@^3.6.0",
"@skyware/jetstream": "npm:@skyware/jetstream@^0.2.5", "@skyware/jetstream": "npm:@skyware/jetstream@^0.2.5",
"@std/assert": "jsr:@std/assert@1" "@std/assert": "jsr:@std/assert@1"
} }

36
deno.lock generated
View File

@@ -20,6 +20,8 @@
"jsr:@std/path@1": "1.1.4", "jsr:@std/path@1": "1.1.4",
"jsr:@std/path@1.0": "1.0.9", "jsr:@std/path@1.0": "1.0.9",
"jsr:@std/path@^1.1.1": "1.1.4", "jsr:@std/path@^1.1.1": "1.1.4",
"npm:@opensearch-project/opensearch@3": "3.6.0",
"npm:@opensearch-project/opensearch@^3.6.0": "3.6.0",
"npm:@skyware/jetstream@~0.2.5": "0.2.5", "npm:@skyware/jetstream@~0.2.5": "0.2.5",
"npm:path-to-regexp@^6.3.0": "6.3.0" "npm:path-to-regexp@^6.3.0": "6.3.0"
}, },
@@ -142,6 +144,17 @@
"unicode-segmenter" "unicode-segmenter"
] ]
}, },
"@opensearch-project/opensearch@3.6.0": {
"integrity": "sha512-ow1A/Z7MBlNL/JZzTY4+M+8psiVh66g0Z7EQSl/qbT0U6zLBsVDYh6nvm8D4e4tIzQtn6ODbA2OsqYGvqZj76g==",
"dependencies": [
"aws4",
"debug",
"hpagent",
"json11",
"ms",
"secure-json-parse"
]
},
"@skyware/jetstream@0.2.5": { "@skyware/jetstream@0.2.5": {
"integrity": "sha512-fM/zs03DLwqRyzZZJFWN20e76KrdqIp97Tlm8Cek+vxn96+tu5d/fx79V6H85L0QN6HvGiX2l9A8hWFqHvYlOA==", "integrity": "sha512-fM/zs03DLwqRyzZZJFWN20e76KrdqIp97Tlm8Cek+vxn96+tu5d/fx79V6H85L0QN6HvGiX2l9A8hWFqHvYlOA==",
"dependencies": [ "dependencies": [
@@ -155,12 +168,31 @@
"@standard-schema/spec@1.1.0": { "@standard-schema/spec@1.1.0": {
"integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==" "integrity": "sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w=="
}, },
"aws4@1.13.2": {
"integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw=="
},
"debug@4.4.3": {
"integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dependencies": [
"ms"
]
},
"esm-env@1.2.2": { "esm-env@1.2.2": {
"integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==" "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA=="
}, },
"event-target-polyfill@0.0.4": { "event-target-polyfill@0.0.4": {
"integrity": "sha512-Gs6RLjzlLRdT8X9ZipJdIZI/Y6/HhRLyq9RdDlCsnpxr/+Nn6bU2EFGuC94GjxqhM+Nmij2Vcq98yoHrU8uNFQ==" "integrity": "sha512-Gs6RLjzlLRdT8X9ZipJdIZI/Y6/HhRLyq9RdDlCsnpxr/+Nn6bU2EFGuC94GjxqhM+Nmij2Vcq98yoHrU8uNFQ=="
}, },
"hpagent@1.2.0": {
"integrity": "sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA=="
},
"json11@2.0.2": {
"integrity": "sha512-HIrd50UPYmP6sqLuLbFVm75g16o0oZrVfxrsY0EEys22klz8mRoWlX9KAEDOSOR9Q34rcxsyC8oDveGrCz5uLQ==",
"bin": true
},
"ms@2.1.3": {
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"partysocket@1.1.12": { "partysocket@1.1.12": {
"integrity": "sha512-079YDW1QZsFwJ8syLmr9xFMbE+VwbK4SpcKSOPVApX8rpIMennkxx0MeWl4oWutP/Zjgy8TMnQZ3FOXTQvu3DA==", "integrity": "sha512-079YDW1QZsFwJ8syLmr9xFMbE+VwbK4SpcKSOPVApX8rpIMennkxx0MeWl4oWutP/Zjgy8TMnQZ3FOXTQvu3DA==",
"dependencies": [ "dependencies": [
@@ -170,6 +202,9 @@
"path-to-regexp@6.3.0": { "path-to-regexp@6.3.0": {
"integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ==" "integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="
}, },
"secure-json-parse@2.7.0": {
"integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw=="
},
"tiny-emitter@2.1.0": { "tiny-emitter@2.1.0": {
"integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==" "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
}, },
@@ -196,6 +231,7 @@
"jsr:@db/sqlite@0.13", "jsr:@db/sqlite@0.13",
"jsr:@oak/oak@^17.2.0", "jsr:@oak/oak@^17.2.0",
"jsr:@std/assert@1", "jsr:@std/assert@1",
"npm:@opensearch-project/opensearch@^3.6.0",
"npm:@skyware/jetstream@~0.2.5" "npm:@skyware/jetstream@~0.2.5"
] ]
} }

View File

@@ -1,3 +1,4 @@
import type { API } from "@opensearch-project/opensearch";
import { log } from "../log.ts"; import { log } from "../log.ts";
const OPENSEARCH_URL = Deno.env.get("OPENSEARCH_URL"); const OPENSEARCH_URL = Deno.env.get("OPENSEARCH_URL");
@@ -185,7 +186,9 @@ export const searchNotes = async (
filters.push({ term: { did: opts.did } }); filters.push({ term: { did: opts.did } });
} }
const body: Record<string, unknown> = { const searchAfter = opts.cursor ? decodeCursor(opts.cursor) : undefined;
const body: API.Search_RequestBody = {
size: limit, size: limit,
query: { query: {
bool: { bool: {
@@ -207,20 +210,15 @@ export const searchNotes = async (
fragment_size: 200, fragment_size: 200,
number_of_fragments: 1, number_of_fragments: 1,
boundary_scanner: "sentence", boundary_scanner: "sentence",
boundary_scanner_locale: "en-US",
}, },
title: { number_of_fragments: 0 }, title: { number_of_fragments: 0 },
}, },
}, },
sort: [{ _score: "desc" }, { rkey: "desc" }], sort: [{ _score: "desc" }, { rkey: "desc" }],
_source: ["did", "rkey", "title", "content", "publishedAt"], _source: ["did", "rkey", "title", "content", "publishedAt"],
...(searchAfter ? { search_after: searchAfter } : {}),
}; };
if (opts.cursor) {
const decoded = decodeCursor(opts.cursor);
if (decoded) body.search_after = decoded;
}
const res = await request("POST", `/${OPENSEARCH_INDEX}/_search`, body); const res = await request("POST", `/${OPENSEARCH_INDEX}/_search`, body);
if (!res.ok) { if (!res.ok) {
const text = await res.text(); const text = await res.text();