@findlane/server 0.6.0 → 0.7.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/dist/index.cjs CHANGED
@@ -144,6 +144,7 @@ class SearchServerClient {
144
144
  return {
145
145
  search: (query = {}, signal) => request("/search", "POST", query, signal),
146
146
  suggest: async (query, signal) => (await request("/suggest", "POST", query, signal)).didYouMean,
147
+ recommendations: (objectID, options = {}, signal) => request("/recommendations", "POST", { objectID, ...options }, signal),
147
148
  upsert: (records, signal) => request("/records", "POST", { records }, signal),
148
149
  getRecord: (objectID, signal) => request(`/records/${encodeURIComponent(objectID)}`, "GET", undefined, signal),
149
150
  upsertOne: (record, options) => writeOne("upsert", record.objectID, record, options),
package/dist/index.d.cts CHANGED
@@ -173,6 +173,31 @@ export type SearchResponse<T> = {
173
173
  * results matched some words only by typo ("Showing results for …"), else null. */
174
174
  didYouMean?: DidYouMean | null;
175
175
  };
176
+ /** How a product's recommendations are served (the recommendations add-on). */
177
+ export type RecommendationsRequest = {
178
+ /** Up to this many products in each list, 1 to 20; 8 by default. */
179
+ limit?: number;
180
+ /** Only picks matching these filters, as in a search (fields configured as filters), such as `{ inStock: true }`. */
181
+ filters?: SearchRequest["filters"];
182
+ /** The record fields to return; all of them by default. */
183
+ attributesToRetrieve?: string[];
184
+ /** Goes with picks cost at most this many times the product; null for no limit. By default, the index's setting. */
185
+ maxPriceRatio?: number | null;
186
+ };
187
+ export type RecommendationHit<T> = {
188
+ id: string;
189
+ score: number | null;
190
+ record: T;
191
+ };
192
+ export type RecommendationsResponse<T> = {
193
+ objectID: string;
194
+ /** false until the product's lists are built; both lists are empty meanwhile. */
195
+ ready: boolean;
196
+ /** Products a shopper would want with this one, the likeliest first; `score` is the decision model's probability. */
197
+ goesWith: RecommendationHit<T>[];
198
+ /** Products a shopper could choose instead, then (unless the index hides them) variants of this one. */
199
+ similar: RecommendationHit<T>[];
200
+ };
176
201
  /** A corrected query. `applied`: the results are already for `q` (a search's "Showing results for");
177
202
  * otherwise searching `q` finds results that the query didn't ("Did you mean"). `changes` lists each
178
203
  * changed part of the query as typed. */
@@ -243,6 +268,9 @@ export declare class SearchServerClient {
243
268
  * same request (its q, filters, and fields matter). Needs the `didYouMean` setting; not counted as
244
269
  * a search. */
245
270
  suggest: (query: SearchRequest, signal?: AbortSignal) => Promise<DidYouMean | null>;
271
+ /** A product's recommendations (the recommendations add-on): products that go with it, and similar products.
272
+ * The API key needs the `search` scope; not counted as a search. */
273
+ recommendations: <R = T>(objectID: string, options?: RecommendationsRequest, signal?: AbortSignal) => Promise<RecommendationsResponse<R>>;
246
274
  upsert: (records: T[], signal?: AbortSignal) => Promise<WriteReceipt>;
247
275
  getRecord: (objectID: string, signal?: AbortSignal) => Promise<RecordSnapshot<T>>;
248
276
  upsertOne: (record: T, options: ConditionalWriteOptions) => Promise<WriteReceipt>;
package/dist/index.d.ts CHANGED
@@ -173,6 +173,31 @@ export type SearchResponse<T> = {
173
173
  * results matched some words only by typo ("Showing results for …"), else null. */
174
174
  didYouMean?: DidYouMean | null;
175
175
  };
176
+ /** How a product's recommendations are served (the recommendations add-on). */
177
+ export type RecommendationsRequest = {
178
+ /** Up to this many products in each list, 1 to 20; 8 by default. */
179
+ limit?: number;
180
+ /** Only picks matching these filters, as in a search (fields configured as filters), such as `{ inStock: true }`. */
181
+ filters?: SearchRequest["filters"];
182
+ /** The record fields to return; all of them by default. */
183
+ attributesToRetrieve?: string[];
184
+ /** Goes with picks cost at most this many times the product; null for no limit. By default, the index's setting. */
185
+ maxPriceRatio?: number | null;
186
+ };
187
+ export type RecommendationHit<T> = {
188
+ id: string;
189
+ score: number | null;
190
+ record: T;
191
+ };
192
+ export type RecommendationsResponse<T> = {
193
+ objectID: string;
194
+ /** false until the product's lists are built; both lists are empty meanwhile. */
195
+ ready: boolean;
196
+ /** Products a shopper would want with this one, the likeliest first; `score` is the decision model's probability. */
197
+ goesWith: RecommendationHit<T>[];
198
+ /** Products a shopper could choose instead, then (unless the index hides them) variants of this one. */
199
+ similar: RecommendationHit<T>[];
200
+ };
176
201
  /** A corrected query. `applied`: the results are already for `q` (a search's "Showing results for");
177
202
  * otherwise searching `q` finds results that the query didn't ("Did you mean"). `changes` lists each
178
203
  * changed part of the query as typed. */
@@ -243,6 +268,9 @@ export declare class SearchServerClient {
243
268
  * same request (its q, filters, and fields matter). Needs the `didYouMean` setting; not counted as
244
269
  * a search. */
245
270
  suggest: (query: SearchRequest, signal?: AbortSignal) => Promise<DidYouMean | null>;
271
+ /** A product's recommendations (the recommendations add-on): products that go with it, and similar products.
272
+ * The API key needs the `search` scope; not counted as a search. */
273
+ recommendations: <R = T>(objectID: string, options?: RecommendationsRequest, signal?: AbortSignal) => Promise<RecommendationsResponse<R>>;
246
274
  upsert: (records: T[], signal?: AbortSignal) => Promise<WriteReceipt>;
247
275
  getRecord: (objectID: string, signal?: AbortSignal) => Promise<RecordSnapshot<T>>;
248
276
  upsertOne: (record: T, options: ConditionalWriteOptions) => Promise<WriteReceipt>;
package/dist/index.js CHANGED
@@ -98,6 +98,7 @@ class SearchServerClient {
98
98
  return {
99
99
  search: (query = {}, signal) => request("/search", "POST", query, signal),
100
100
  suggest: async (query, signal) => (await request("/suggest", "POST", query, signal)).didYouMean,
101
+ recommendations: (objectID, options = {}, signal) => request("/recommendations", "POST", { objectID, ...options }, signal),
101
102
  upsert: (records, signal) => request("/records", "POST", { records }, signal),
102
103
  getRecord: (objectID, signal) => request(`/records/${encodeURIComponent(objectID)}`, "GET", undefined, signal),
103
104
  upsertOne: (record, options) => writeOne("upsert", record.objectID, record, options),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@findlane/server",
3
- "version": "0.6.0",
3
+ "version": "0.7.0",
4
4
  "description": "Findlane server SDK: upload catalogs, manage index settings, and search with a secret workspace API key.",
5
5
  "keywords": ["findlane", "search", "full-text search", "typo tolerance", "ecommerce search", "search api", "sdk"],
6
6
  "license": "MIT",