Skip to content
Open
Show file tree
Hide file tree
Changes from 22 commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
2fcafc0
Improve settings
flevi29 Feb 4, 2025
9692533
Fix formatting
flevi29 Feb 4, 2025
ab6b24b
Merge branch 'main' into improve-settings
flevi29 Feb 6, 2025
80b6db7
Merge branch 'main' into improve-settings
flevi29 Feb 17, 2025
4c85a6f
Merge branch 'main' into improve-settings
flevi29 Mar 2, 2025
d21ecfd
Merge with main
flevi29 Mar 20, 2025
9a82d5e
Merge with main
flevi29 Mar 21, 2025
83a1b09
Merge with main
flevi29 Mar 26, 2025
d845050
Fix lint issue
flevi29 Mar 26, 2025
12d5c37
Merge with main
flevi29 Apr 1, 2025
b851425
Make adjustments, fixes
flevi29 Apr 10, 2025
86a8f89
Remove unnecessary type params
flevi29 Apr 10, 2025
3095a19
Shorten code
flevi29 Apr 10, 2025
d35cc36
Adjust documentation, fix test
flevi29 Apr 11, 2025
beb41ea
Merge branch 'main' into improve-settings
flevi29 Apr 11, 2025
65fb90e
Documentation
flevi29 Apr 11, 2025
0dfc39f
Merge with main
flevi29 Apr 22, 2025
a8b99d1
Progress
flevi29 Apr 24, 2025
f6dbc99
Refactor settings tests
flevi29 Apr 24, 2025
9e9fd85
Minor changes
flevi29 Apr 25, 2025
7b83644
Improve tests
flevi29 Apr 25, 2025
b523bca
Merge branch 'main' into improve-settings
flevi29 Apr 29, 2025
4dee0f7
Merge with main
flevi29 May 19, 2025
9a95477
Use randomUUID instead of fixed UUID
flevi29 May 19, 2025
c52f078
Merge with main, and add vector store experimental feature
flevi29 Sep 23, 2025
4bda5ad
Fix type issue, temporarily fix test error
flevi29 Sep 23, 2025
32d171c
Fix experimental settings test
flevi29 Sep 23, 2025
5966914
Fix test
flevi29 Sep 23, 2025
ceb2db6
Adjustments, docs
flevi29 Sep 25, 2025
77b0797
Adjustments
flevi29 Sep 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
166 changes: 83 additions & 83 deletions .code-samples.meilisearch.yaml

Large diffs are not rendered by default.

116 changes: 58 additions & 58 deletions README.md

Large diffs are not rendered by default.

908 changes: 56 additions & 852 deletions src/indexes.ts

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions src/meilisearch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
ExtraRequestInit,
Network,
RecordAny,
RuntimeTogglableFeatures,
} from "./types/index.js";
import { ErrorStatusCode } from "./types/index.js";
import { HttpRequests } from "./http-requests.js";
Expand Down Expand Up @@ -454,4 +455,25 @@
path: "snapshots",
});
}

///
/// EXPERIMENTAL-FEATURES
///

/** {@link https://www.meilisearch.com/docs/reference/api/experimental_features#get-all-experimental-features} */
async getExperimentalFeatures(): Promise<RuntimeTogglableFeatures> {
return await this.httpRequest.get({
path: "experimental-features",
});
}

Check warning on line 468 in src/meilisearch.ts

View check run for this annotation

Codecov / codecov/patch

src/meilisearch.ts#L465-L468

Added lines #L465 - L468 were not covered by tests

/** {@link https://www.meilisearch.com/docs/reference/api/experimental_features#configure-experimental-features} */
async updateExperimentalFeatures(
runtimeTogglableFeatures: RuntimeTogglableFeatures,
): Promise<RuntimeTogglableFeatures> {
return await this.httpRequest.patch({
path: "experimental-features",
body: runtimeTogglableFeatures,
});
}
}
66 changes: 66 additions & 0 deletions src/settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
import type { HttpRequests } from "./http-requests.js";
import type { HttpRequestsWithEnqueuedTaskPromise } from "./task.js";
import type {
EnqueuedTaskPromise,
SingleUpdatableSettings,
RecordAny,
} from "./types/index.js";

/** Each setting property mapped to their REST method required for updates. */
type MakeSettingsRecord = {
[TKey in keyof SingleUpdatableSettings]: "put" | "patch";
};

/** Each setting property mapped to its get, update and reset functions. */
export type SettingFns = {
[TKey in keyof SingleUpdatableSettings as `get${Capitalize<TKey>}`]: () => Promise<
SingleUpdatableSettings[TKey]
>;
} & {
[TKey in keyof SingleUpdatableSettings as `update${Capitalize<TKey>}`]: (
body: SingleUpdatableSettings[TKey],
) => EnqueuedTaskPromise;
} & {
[TKey in keyof SingleUpdatableSettings as `reset${Capitalize<TKey>}`]: () => EnqueuedTaskPromise;
};

function capitalize(str: string): string {
return str.charAt(0).toUpperCase() + str.slice(1);
}

function camelToKebabCase(str: string): string {
return str.replace(/[A-Z]/g, (letter) => `-${letter.toLowerCase()}`);
}

/** Returns an object containing all the setting functions. */
export function makeSettingFns(
httpRequest: HttpRequests,
httpRequestsWithTask: HttpRequestsWithEnqueuedTaskPromise,
basePath: string,
opts: MakeSettingsRecord,
): SettingFns {
const settingFns = {} as RecordAny;

for (const [name, method] of Object.entries(opts)) {
const uppercaseName = capitalize(name);
const path = `${basePath}/${camelToKebabCase(name)}`;

settingFns[`get${uppercaseName}`] = async function (): Promise<
SingleUpdatableSettings[keyof typeof opts]
> {
return await httpRequest.get({ path });
};

settingFns[`update${uppercaseName}`] = function (
body: SingleUpdatableSettings[keyof typeof opts],
): EnqueuedTaskPromise {
return httpRequestsWithTask[method]({ path, body });
};

settingFns[`reset${uppercaseName}`] = function (): EnqueuedTaskPromise {
return httpRequestsWithTask.delete({ path });
};
}

return settingFns as SettingFns;
}
14 changes: 14 additions & 0 deletions src/types/experimental-features.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/**
* {@link https://www.meilisearch.com/docs/reference/api/experimental_features#experimental-features-object}
*
* @see `meilisearch::routes::features::RuntimeTogglableFeatures`
*/
export type RuntimeTogglableFeatures = {
metrics?: boolean | null;
logsRoute?: boolean | null;
editDocumentsByFunction?: boolean | null;
containsFilter?: boolean | null;
network?: boolean | null;
getTaskDocumentsRoute?: boolean | null;
compositeEmbedders?: boolean | null;
};
2 changes: 2 additions & 0 deletions src/types/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
export * from "./experimental-features.js";
export * from "./settings.js";
export * from "./task_and_batch.js";
export * from "./token.js";
export * from "./types.js";
224 changes: 224 additions & 0 deletions src/types/settings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
import type { PascalToCamelCase } from "./shared.js";

/** @see `milli::filterable_attributes_rules::FilterFeatures` */
export type FilterFeatures = {
equality?: boolean;
comparison?: boolean;
};

/** @see `milli::filterable_attributes_rules::FilterableAttributesFeatures` */
export type FilterableAttributesFeatures = {
facetSearch?: boolean;
filter?: FilterFeatures;
};

/** @see `milli::filterable_attributes_rules::FilterableAttributesPatterns` */
export type FilterableAttributesPatterns = {
attributePatterns: string[];
features?: FilterableAttributesFeatures;
};

/** @see `milli::filterable_attributes_rules::FilterableAttributesRule` */
export type FilterableAttributesRule = string | FilterableAttributesPatterns;

/** Deeply map every property of a record to itself excluding null. */
type NonNullableDeepRecordValues<T> = {
[TKey in keyof T]: Exclude<NonNullableDeepRecordValues<T[TKey]>, null>;
};

/** Map properties of a record to be optional and nullable. */
type PartialAndNullable<T> = { [P in keyof T]?: T[P] | null };

/**
* {@link https://www.meilisearch.com/docs/reference/api/settings#proximity-precision}
*
* @see `meilisearch_types::settings::ProximityPrecisionView`
*/
export type ProximityPrecisionView = PascalToCamelCase<
"ByWord" | "ByAttribute"
>;

/**
* @see `minWordSizeForTypos` at {@link https://www.meilisearch.com/docs/reference/api/settings#typo-tolerance}
*
* @see `meilisearch_types::settings::MinWordSizeTyposSetting`
*/
export type MinWordSizeTyposSetting = PartialAndNullable<{
oneTypo: number;
twoTypos: number;
}>;

/**
* {@link https://www.meilisearch.com/docs/reference/api/settings#typo-tolerance}
*
* @see `meilisearch_types::settings::TypoSettings`
*/
export type TypoSettings = PartialAndNullable<{
enabled: boolean;
minWordSizeForTypos: MinWordSizeTyposSetting;
disableOnWords: string[];
disableOnAttributes: string[];
}>;

/**
* @see `sortFacetValuesBy` at {@link https://www.meilisearch.com/docs/reference/api/settings#faceting}
* @see `meilisearch_types::facet_values_sort::FacetValuesSort`
*/
export type FacetValuesSort = PascalToCamelCase<"Alpha" | "Count">;

/**
* {@link https://www.meilisearch.com/docs/reference/api/settings#faceting}
*
* @see `meilisearch_types::settings::FacetingSettings`
*/
export type FacetingSettings = PartialAndNullable<{
maxValuesPerFacet: number;
sortFacetValuesBy: Record<string, FacetValuesSort>;
}>;

/**
* {@link https://www.meilisearch.com/docs/reference/api/settings#pagination}
*
* @see `meilisearch_types::settings::PaginationSettings`
*/
export type PaginationSettings = PartialAndNullable<{ maxTotalHits: number }>;

/**
* `distribution` at
* {@link https://www.meilisearch.com/docs/reference/api/settings#embedders}
*
* @see `milli::vector::DistributionShift`
*/
export type DistributionShift = {
mean: number;
sigma: number;
};

/**
* `source` at
* {@link https://www.meilisearch.com/docs/reference/api/settings#embedders}
*
* @see `milli::vector::settings::EmbedderSource`
*/
export type EmbedderSource = PascalToCamelCase<
"OpenAi" | "HuggingFace" | "Ollama" | "UserProvided" | "Rest" | "Composite"
>;

/** @see `milli::vector::hf::OverridePooling` */
export type OverridePooling = PascalToCamelCase<
"UseModel" | "ForceCls" | "ForceMean"
>;

/** @see `milli::vector::settings::SubEmbeddingSettings` */
export type SubEmbeddingSettings = PartialAndNullable<{
source: EmbedderSource;
model: string;
revision: string;
pooling: OverridePooling;
apiKey: string;
dimensions: number;
documentTemplate: string;
documentTemplateMaxBytes: number;
url: string;
request: unknown;
response: unknown;
headers: Record<string, string>;
}>;

/**
* {@link https://www.meilisearch.com/docs/reference/api/settings#embedders}
*
* @see `milli::vector::settings::EmbeddingSettings`
*/
export type EmbeddingSettings = PartialAndNullable<{
distribution: DistributionShift;
binaryQuantized: boolean;
searchEmbedder: SubEmbeddingSettings;
indexingEmbedder: SubEmbeddingSettings;
}> &
SubEmbeddingSettings;

/**
* {@link https://www.meilisearch.com/docs/reference/api/settings#localized-attributes}
*
* @see `meilisearch_types::locales::LocalizedAttributesRuleView`
*/
export type LocalizedAttributesRuleView = {
/** @see `milli::attribute_patterns::AttributePatterns` */
attributePatterns: string[];
/** @see `meilisearch_types::locales::Locale` */
locales: string[];
};

/**
* {@link https://www.meilisearch.com/docs/reference/api/settings#prefix-search}
*
* @see `meilisearch_types::settings::PrefixSearchSettings`
*/
export type PrefixSearchSettings = PascalToCamelCase<
"IndexingTime" | "Disabled"
>;

/** @see `meilisearch_types::settings::RankingRuleView` */
export type RankingRuleView =
| PascalToCamelCase<
"Words" | "Typo" | "Proximity" | "Attribute" | "Sort" | "Exactness"
>
| `${string}:${"asc" | "desc"}`;

/** A version of {@link Settings} that can be used to update the settings. */
export type UpdatableSettings = PartialAndNullable<{
/** {@link https://www.meilisearch.com/docs/reference/api/settings#displayed-attributes} */
displayedAttributes: string[];
/** {@link https://www.meilisearch.com/docs/reference/api/settings#searchable-attributes} */
searchableAttributes: string[];
/** {@link https://www.meilisearch.com/docs/reference/api/settings#filterable-attributes} */
filterableAttributes: FilterableAttributesRule[];
/** {@link https://www.meilisearch.com/docs/reference/api/settings#sortable-attributes} */
sortableAttributes: string[];
/** {@link https://www.meilisearch.com/docs/reference/api/settings#ranking-rules} */
rankingRules: RankingRuleView[];
/** {@link https://www.meilisearch.com/docs/reference/api/settings#stop-words} */
stopWords: string[];
/** {@link https://www.meilisearch.com/docs/reference/api/settings#non-separator-tokens} */
nonSeparatorTokens: string[];
/** {@link https://www.meilisearch.com/docs/reference/api/settings#separator-tokens} */
separatorTokens: string[];
/** {@link https://www.meilisearch.com/docs/reference/api/settings#dictionary} */
dictionary: string[];
/** {@link https://www.meilisearch.com/docs/reference/api/settings#synonyms} */
synonyms: Record<string, string[]>;
/** {@link https://www.meilisearch.com/docs/reference/api/settings#distinct-attribute} */
distinctAttribute: string;
/** {@link https://www.meilisearch.com/docs/reference/api/settings#proximity-precision} */
proximityPrecision: ProximityPrecisionView;
/** {@link https://www.meilisearch.com/docs/reference/api/settings#typo-tolerance} */
typoTolerance: TypoSettings;
/** {@link https://www.meilisearch.com/docs/reference/api/settings#faceting} */
faceting: FacetingSettings;
/** {@link https://www.meilisearch.com/docs/reference/api/settings#pagination} */
pagination: PaginationSettings;
/** {@link https://www.meilisearch.com/docs/reference/api/settings#embedders} */
embedders: PartialAndNullable<Record<string, EmbeddingSettings>>;
/** {@link https://www.meilisearch.com/docs/reference/api/settings#search-cutoff} */
searchCutoffMs: number;
/** {@link https://www.meilisearch.com/docs/reference/api/settings#localized-attributes} */
localizedAttributes: LocalizedAttributesRuleView[];
/** {@link https://www.meilisearch.com/docs/reference/api/settings#facet-search} */
facetSearch: boolean;
/** {@link https://www.meilisearch.com/docs/reference/api/settings#prefix-search} */
prefixSearch: PrefixSearchSettings;
}>;

/**
* A version of {@link UpdatableSettings}, the first layer of properties of which
* is used to update or get individual settings.
*/
export type SingleUpdatableSettings = Required<UpdatableSettings>;

/**
* {@link https://www.meilisearch.com/docs/reference/api/settings#body}
*
* @see `meilisearch_types::settings::Settings`
*/
export type Settings = NonNullableDeepRecordValues<UpdatableSettings>;
12 changes: 2 additions & 10 deletions src/types/shared.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import type { RecordAny } from "./types.js";

export type CursorResults<T> = {
results: T[];
limit: number;
Expand All @@ -8,11 +6,5 @@ export type CursorResults<T> = {
total: number;
};

export type NonNullableDeepRecordValues<T> = {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[P in keyof T]: T[P] extends any[]
? Array<NonNullableDeepRecordValues<T[P][number]>>
: T[P] extends RecordAny
? NonNullableDeepRecordValues<T[P]>
: NonNullable<T[P]>;
};
// taken from https://stackoverflow.com/a/65642944
export type PascalToCamelCase<S extends string> = Uncapitalize<S>;
4 changes: 2 additions & 2 deletions src/types/task_and_batch.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Settings } from "./types.js";
import type { UpdatableSettings } from "./settings.js";
import type { CursorResults } from "./shared.js";
import type { MeiliSearchErrorResponse } from "./types.js";

Expand Down Expand Up @@ -97,7 +97,7 @@ export type TaskUidOrEnqueuedTask = EnqueuedTask["taskUid"] | EnqueuedTask;
export type IndexSwap = { indexes: [string, string] };

/** {@link https://www.meilisearch.com/docs/reference/api/tasks#details} */
export type TaskDetails = Settings & {
export type TaskDetails = UpdatableSettings & {
receivedDocuments?: number;
indexedDocuments?: number;
editedDocuments?: number;
Expand Down
Loading