@basaltkit/search 1.0.0 → 1.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/LICENSE +1 -1
- package/dist/index.d.ts +11 -1
- package/dist/index.js +20 -1
- package/package.json +1 -1
package/LICENSE
CHANGED
package/dist/index.d.ts
CHANGED
|
@@ -103,6 +103,9 @@ declare class MeilisearchError extends BasaltError {
|
|
|
103
103
|
readonly httpStatus: number;
|
|
104
104
|
constructor(httpStatus: number, message: string);
|
|
105
105
|
}
|
|
106
|
+
declare class SearchFilterFieldError extends BasaltError {
|
|
107
|
+
constructor(field: string);
|
|
108
|
+
}
|
|
106
109
|
interface MeilisearchDriverOptions {
|
|
107
110
|
host: string;
|
|
108
111
|
apiKey?: string;
|
|
@@ -156,7 +159,14 @@ interface SearchPluginOptions {
|
|
|
156
159
|
indexes?: IndexDefinition[];
|
|
157
160
|
/** Rules keeping indexes in sync with domain hooks. */
|
|
158
161
|
sync?: SyncRule[];
|
|
162
|
+
/**
|
|
163
|
+
* Throw if an index fails to register at boot. Default `false`: a search
|
|
164
|
+
* backend that's down or misconfigured logs a warning and the app boots
|
|
165
|
+
* anyway (search stays degraded until the backend is reachable), so an outage
|
|
166
|
+
* never blocks unrelated work — including CLI commands that don't use search.
|
|
167
|
+
*/
|
|
168
|
+
failOnRegisterError?: boolean;
|
|
159
169
|
}
|
|
160
170
|
declare function searchPlugin(options?: SearchPluginOptions): _basaltkit_core.BasaltPlugin<unknown>;
|
|
161
171
|
|
|
162
|
-
export { type IndexDefinition, MeilisearchDriver, type MeilisearchDriverOptions, MeilisearchError, MemorySearchDriver, SEARCH, Search, type SearchDocument, type SearchDriver, type SearchHit, type SearchOptions, type SearchPluginOptions, type SearchQuery, type SearchResult, type SyncRule, TenantRequiredError, defineIndex, searchPlugin, syncRule };
|
|
172
|
+
export { type IndexDefinition, MeilisearchDriver, type MeilisearchDriverOptions, MeilisearchError, MemorySearchDriver, SEARCH, Search, type SearchDocument, type SearchDriver, SearchFilterFieldError, type SearchHit, type SearchOptions, type SearchPluginOptions, type SearchQuery, type SearchResult, type SyncRule, TenantRequiredError, defineIndex, searchPlugin, syncRule };
|
package/dist/index.js
CHANGED
|
@@ -128,6 +128,12 @@ var MeilisearchError = class extends BasaltError2 {
|
|
|
128
128
|
}
|
|
129
129
|
httpStatus;
|
|
130
130
|
};
|
|
131
|
+
var SearchFilterFieldError = class extends BasaltError2 {
|
|
132
|
+
constructor(field) {
|
|
133
|
+
super("SEARCH_INVALID_FILTER_FIELD", `Invalid filter field name: ${JSON.stringify(field)}.`);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
var SAFE_FILTER_FIELD = /^[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_]*)*$/;
|
|
131
137
|
var primaryKey = (tenantId, id) => Buffer.from(`${tenantId}::${id}`).toString("base64url");
|
|
132
138
|
var quote = (value) => JSON.stringify(value);
|
|
133
139
|
var MeilisearchDriver = class {
|
|
@@ -182,6 +188,7 @@ var MeilisearchDriver = class {
|
|
|
182
188
|
buildFilter(tenantId, filters) {
|
|
183
189
|
const parts = [`tenantId = ${quote(tenantId)}`];
|
|
184
190
|
for (const [field, value] of Object.entries(filters ?? {})) {
|
|
191
|
+
if (!SAFE_FILTER_FIELD.test(field)) throw new SearchFilterFieldError(field);
|
|
185
192
|
parts.push(Array.isArray(value) ? `${field} IN [${value.map(quote).join(", ")}]` : `${field} = ${quote(value)}`);
|
|
186
193
|
}
|
|
187
194
|
return parts.join(" AND ");
|
|
@@ -221,7 +228,18 @@ function searchPlugin(options = {}) {
|
|
|
221
228
|
async boot({ container, hooks }) {
|
|
222
229
|
const search = container.get(SEARCH);
|
|
223
230
|
if (driver.register) {
|
|
224
|
-
for (const index of options.indexes ?? [])
|
|
231
|
+
for (const index of options.indexes ?? []) {
|
|
232
|
+
try {
|
|
233
|
+
await driver.register(index);
|
|
234
|
+
} catch (error) {
|
|
235
|
+
if (options.failOnRegisterError) throw error;
|
|
236
|
+
console.warn(
|
|
237
|
+
`[basalt:search] could not register index "${index.name}": ${String(
|
|
238
|
+
error?.message ?? error
|
|
239
|
+
)} \u2014 search is degraded until the backend is reachable.`
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
225
243
|
}
|
|
226
244
|
for (const rule of options.sync ?? []) {
|
|
227
245
|
hooks.on(rule.hook, async (payload) => {
|
|
@@ -243,6 +261,7 @@ export {
|
|
|
243
261
|
MemorySearchDriver,
|
|
244
262
|
SEARCH,
|
|
245
263
|
Search,
|
|
264
|
+
SearchFilterFieldError,
|
|
246
265
|
TenantRequiredError,
|
|
247
266
|
defineIndex,
|
|
248
267
|
searchPlugin,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@basaltkit/search",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Full-text search for Basalt: tenant-scoped indexing and querying with a pluggable driver (in-memory for dev/test, Meilisearch for production) and automatic sync from domain events.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|