diff --git a/typesense/alias.go b/typesense/alias.go index 5837a81e..1b8b6a32 100644 --- a/typesense/alias.go +++ b/typesense/alias.go @@ -8,7 +8,19 @@ import ( // AliasInterface is a type for Alias API operations type AliasInterface interface { + // Retrieve an alias. + // + // Find out which collection an alias points to by fetching it + // + // HTTP: GET /aliases/{aliasName} + // + // See: https://typesense.org/docs/latest/api/collections.html Retrieve(ctx context.Context) (*api.CollectionAlias, error) + // Delete an alias. + // + // HTTP: DELETE /aliases/{aliasName} + // + // See: https://typesense.org/docs/latest/api/collections.html Delete(ctx context.Context) (*api.CollectionAlias, error) } @@ -17,6 +29,13 @@ type alias struct { name string } +// Retrieve an alias. +// +// # Find out which collection an alias points to by fetching it +// +// HTTP: GET /aliases/{aliasName} +// +// See: https://typesense.org/docs/latest/api/collections.html func (a *alias) Retrieve(ctx context.Context) (*api.CollectionAlias, error) { response, err := a.apiClient.GetAliasWithResponse(ctx, a.name) if err != nil { @@ -28,6 +47,11 @@ func (a *alias) Retrieve(ctx context.Context) (*api.CollectionAlias, error) { return response.JSON200, nil } +// Delete an alias. +// +// HTTP: DELETE /aliases/{aliasName} +// +// See: https://typesense.org/docs/latest/api/collections.html func (a *alias) Delete(ctx context.Context) (*api.CollectionAlias, error) { response, err := a.apiClient.DeleteAliasWithResponse(ctx, a.name) if err != nil { diff --git a/typesense/aliases.go b/typesense/aliases.go index fd75390f..c1d78f2d 100644 --- a/typesense/aliases.go +++ b/typesense/aliases.go @@ -8,7 +8,21 @@ import ( // AliasesInterface is a type for Aliases API operations type AliasesInterface interface { + // Create or update a collection alias. + // + // Create or update a collection alias. An alias is a virtual collection name that points to a real collection. If you're familiar with symbolic links on Linux, it's very similar to that. Aliases are useful when you want to reindex your data in the background on a new collection and switch your application to it without any changes to your code. + // + // HTTP: PUT /aliases/{aliasName} + // + // See: https://typesense.org/docs/latest/api/collections.html Upsert(ctx context.Context, aliasName string, aliasSchema *api.CollectionAliasSchema) (*api.CollectionAlias, error) + // List all aliases. + // + // List all aliases and the corresponding collections that they map to. + // + // HTTP: GET /aliases + // + // See: https://typesense.org/docs/latest/api/collections.html Retrieve(ctx context.Context) ([]*api.CollectionAlias, error) } @@ -17,6 +31,13 @@ type aliases struct { apiClient APIClientInterface } +// Create or update a collection alias. +// +// Create or update a collection alias. An alias is a virtual collection name that points to a real collection. If you're familiar with symbolic links on Linux, it's very similar to that. Aliases are useful when you want to reindex your data in the background on a new collection and switch your application to it without any changes to your code. +// +// HTTP: PUT /aliases/{aliasName} +// +// See: https://typesense.org/docs/latest/api/collections.html func (a *aliases) Upsert(ctx context.Context, aliasName string, aliasSchema *api.CollectionAliasSchema) (*api.CollectionAlias, error) { response, err := a.apiClient.UpsertAliasWithResponse(ctx, aliasName, api.UpsertAliasJSONRequestBody(*aliasSchema)) @@ -29,6 +50,13 @@ func (a *aliases) Upsert(ctx context.Context, aliasName string, aliasSchema *api return response.JSON200, nil } +// List all aliases. +// +// List all aliases and the corresponding collections that they map to. +// +// HTTP: GET /aliases +// +// See: https://typesense.org/docs/latest/api/collections.html func (a *aliases) Retrieve(ctx context.Context) ([]*api.CollectionAlias, error) { response, err := a.apiClient.GetAliasesWithResponse(ctx) if err != nil { diff --git a/typesense/analytics_events.go b/typesense/analytics_events.go index 7812063e..5822c26a 100644 --- a/typesense/analytics_events.go +++ b/typesense/analytics_events.go @@ -7,7 +7,21 @@ import ( ) type AnalyticsEventsInterface interface { + // Create an analytics event. + // + // Submit a single analytics event. The event must correspond to an existing analytics rule by name. + // + // HTTP: POST /analytics/events + // + // See: https://typesense.org/docs/latest/api/analytics-query-suggestions.html Create(ctx context.Context, eventSchema *api.AnalyticsEvent) (*api.AnalyticsEventCreateResponse, error) + // Retrieve analytics events. + // + // Retrieve the most recent events for a user and rule. + // + // HTTP: GET /analytics/events + // + // See: https://typesense.org/docs/latest/api/analytics-query-suggestions.html Retrieve(ctx context.Context, params *api.GetAnalyticsEventsParams) (*api.AnalyticsEventsResponse, error) } @@ -15,6 +29,13 @@ type analyticsEvents struct { apiClient APIClientInterface } +// Create an analytics event. +// +// Submit a single analytics event. The event must correspond to an existing analytics rule by name. +// +// HTTP: POST /analytics/events +// +// See: https://typesense.org/docs/latest/api/analytics-query-suggestions.html func (a *analyticsEvents) Create(ctx context.Context, eventSchema *api.AnalyticsEvent) (*api.AnalyticsEventCreateResponse, error) { response, err := a.apiClient.CreateAnalyticsEventWithResponse(ctx, api.CreateAnalyticsEventJSONRequestBody(*eventSchema)) if err != nil { @@ -26,6 +47,13 @@ func (a *analyticsEvents) Create(ctx context.Context, eventSchema *api.Analytics return response.JSON200, nil } +// Retrieve analytics events. +// +// Retrieve the most recent events for a user and rule. +// +// HTTP: GET /analytics/events +// +// See: https://typesense.org/docs/latest/api/analytics-query-suggestions.html func (a *analyticsEvents) Retrieve(ctx context.Context, params *api.GetAnalyticsEventsParams) (*api.AnalyticsEventsResponse, error) { response, err := a.apiClient.GetAnalyticsEventsWithResponse(ctx, params) if err != nil { diff --git a/typesense/analytics_rule.go b/typesense/analytics_rule.go index 719af7e5..7a7740aa 100644 --- a/typesense/analytics_rule.go +++ b/typesense/analytics_rule.go @@ -7,8 +7,29 @@ import ( ) type AnalyticsRuleInterface interface { + // Delete an analytics rule. + // + // Permanently deletes an analytics rule, given it's name + // + // HTTP: DELETE /analytics/rules/{ruleName} + // + // See: https://typesense.org/docs/latest/api/analytics-query-suggestions.html Delete(ctx context.Context) (*api.AnalyticsRule, error) + // Retrieves an analytics rule. + // + // Retrieve the details of an analytics rule, given it's name + // + // HTTP: GET /analytics/rules/{ruleName} + // + // See: https://typesense.org/docs/latest/api/analytics-query-suggestions.html Retrieve(ctx context.Context) (*api.AnalyticsRule, error) + // Upserts an analytics rule. + // + // Upserts an analytics rule with the given name. + // + // HTTP: PUT /analytics/rules/{ruleName} + // + // See: https://typesense.org/docs/latest/api/analytics-query-suggestions.html Update(ctx context.Context, ruleSchema *api.AnalyticsRuleUpdate) (*api.AnalyticsRule, error) } @@ -17,6 +38,13 @@ type analyticsRule struct { ruleName string } +// Delete an analytics rule. +// +// # Permanently deletes an analytics rule, given it's name +// +// HTTP: DELETE /analytics/rules/{ruleName} +// +// See: https://typesense.org/docs/latest/api/analytics-query-suggestions.html func (a *analyticsRule) Delete(ctx context.Context) (*api.AnalyticsRule, error) { response, err := a.apiClient.DeleteAnalyticsRuleWithResponse(ctx, a.ruleName) if err != nil { @@ -28,6 +56,13 @@ func (a *analyticsRule) Delete(ctx context.Context) (*api.AnalyticsRule, error) return response.JSON200, nil } +// Retrieves an analytics rule. +// +// # Retrieve the details of an analytics rule, given it's name +// +// HTTP: GET /analytics/rules/{ruleName} +// +// See: https://typesense.org/docs/latest/api/analytics-query-suggestions.html func (a *analyticsRule) Retrieve(ctx context.Context) (*api.AnalyticsRule, error) { response, err := a.apiClient.RetrieveAnalyticsRuleWithResponse(ctx, a.ruleName) if err != nil { @@ -39,6 +74,13 @@ func (a *analyticsRule) Retrieve(ctx context.Context) (*api.AnalyticsRule, error return response.JSON200, nil } +// Upserts an analytics rule. +// +// Upserts an analytics rule with the given name. +// +// HTTP: PUT /analytics/rules/{ruleName} +// +// See: https://typesense.org/docs/latest/api/analytics-query-suggestions.html func (a *analyticsRule) Update(ctx context.Context, ruleSchema *api.AnalyticsRuleUpdate) (*api.AnalyticsRule, error) { response, err := a.apiClient.UpsertAnalyticsRuleWithResponse(ctx, a.ruleName, api.UpsertAnalyticsRuleJSONRequestBody(*ruleSchema)) if err != nil { diff --git a/typesense/analytics_rules.go b/typesense/analytics_rules.go index 8a1da99f..edc93fd8 100644 --- a/typesense/analytics_rules.go +++ b/typesense/analytics_rules.go @@ -11,7 +11,21 @@ import ( ) type AnalyticsRulesInterface interface { + // Create analytics rule(s). + // + // Create one or more analytics rules. You can send a single rule object or an array of rule objects. + // + // HTTP: POST /analytics/rules + // + // See: https://typesense.org/docs/latest/api/analytics-query-suggestions.html Create(ctx context.Context, rules []*api.AnalyticsRuleCreate) ([]*api.AnalyticsRule, error) + // Retrieve analytics rules. + // + // Retrieve all analytics rules. Use the optional rule_tag filter to narrow down results. + // + // HTTP: GET /analytics/rules + // + // See: https://typesense.org/docs/latest/api/analytics-query-suggestions.html Retrieve(ctx context.Context) ([]*api.AnalyticsRule, error) } @@ -19,6 +33,13 @@ type analyticsRules struct { apiClient APIClientInterface } +// Create analytics rule(s). +// +// Create one or more analytics rules. You can send a single rule object or an array of rule objects. +// +// HTTP: POST /analytics/rules +// +// See: https://typesense.org/docs/latest/api/analytics-query-suggestions.html func (a *analyticsRules) Create(ctx context.Context, rules []*api.AnalyticsRuleCreate) ([]*api.AnalyticsRule, error) { // Convert []*AnalyticsRuleCreate to []AnalyticsRuleCreate for the API call ruleCreates := make([]api.AnalyticsRuleCreate, len(rules)) @@ -73,6 +94,13 @@ func (a *analyticsRules) Create(ctx context.Context, rules []*api.AnalyticsRuleC return nil, fmt.Errorf("failed to parse response: %s", string(responseBody)) } +// Retrieve analytics rules. +// +// Retrieve all analytics rules. Use the optional rule_tag filter to narrow down results. +// +// HTTP: GET /analytics/rules +// +// See: https://typesense.org/docs/latest/api/analytics-query-suggestions.html func (a *analyticsRules) Retrieve(ctx context.Context) ([]*api.AnalyticsRule, error) { response, err := a.apiClient.RetrieveAnalyticsRulesWithResponse(ctx, &api.RetrieveAnalyticsRulesParams{}) if err != nil { diff --git a/typesense/api/generator/docgen.go b/typesense/api/generator/docgen.go new file mode 100644 index 00000000..5448c330 --- /dev/null +++ b/typesense/api/generator/docgen.go @@ -0,0 +1,443 @@ +package main + +import ( + "fmt" + "go/ast" + "go/parser" + "go/token" + "log" + "os" + "path/filepath" + "sort" + "strings" + "unicode" + + "gopkg.in/yaml.v3" +) + +// reads the OpenAPI spec, walks each wrapper .go file in +// wrapperDir, and rewrites doc comments on methods whose body issues a single +// direct apiClient.(...) call. The comment text comes verbatim from the +// spec's summary/description for the matched operation. Interface methods that +// match an annotated impl method get the same comment. +func injectWrapperDocs(specPath, wrapperDir string) { + log.Println("Injecting wrapper doc comments from OpenAPI spec") + + ops, err := loadOpIndex(specPath) + if err != nil { + log.Printf("docgen: failed to load spec: %s", err) + return + } + + // Build map of Go func names (as oapi-codegen emits) → operation info. + funcToOp := make(map[string]*opInfo, len(ops)*4) + for _, op := range ops { + for _, name := range goFuncNamesForOp(op.OperationID) { + funcToOp[name] = op + } + } + + entries, err := os.ReadDir(wrapperDir) + if err != nil { + log.Printf("docgen: cannot read wrapper dir: %s", err) + return + } + + touched := 0 + for _, e := range entries { + if e.IsDir() || !strings.HasSuffix(e.Name(), ".go") { + continue + } + if strings.HasSuffix(e.Name(), "_test.go") { + continue + } + path := filepath.Join(wrapperDir, e.Name()) + changed, err := annotateFile(path, funcToOp) + if err != nil { + log.Printf("docgen: %s: %s", e.Name(), err) + continue + } + if changed { + touched++ + } + } + log.Printf("docgen: updated %d wrapper file(s)", touched) +} + +type opInfo struct { + OperationID string + Summary string + Description string + Method string + Path string + Tag string +} + +const docsBaseURL = "https://typesense.org/docs/latest/api/" + +var tagToDocs = map[string]string{ + "collections": "collections.html", + "documents": "documents.html", + "keys": "api-keys.html", + "aliases": "collection-alias.html", + "synonyms": "synonyms.html", + "curation_sets": "curation.html", + "stopwords": "stopwords.html", + "presets": "search.html#presets", + "analytics": "analytics-query-suggestions.html", + "conversations": "conversational-search-rag.html", + "stemming": "stemming.html", + "nl_search_models": "natural-language-search.html", + "debug": "cluster-operations.html#debug", + "health": "cluster-operations.html#health", + "operations": "cluster-operations.html", +} + +func loadOpIndex(specPath string) (map[string]*opInfo, error) { + f, err := os.Open(specPath) + if err != nil { + return nil, err + } + defer f.Close() + + var spec yml + if err := yaml.NewDecoder(f).Decode(&spec); err != nil { + return nil, err + } + + ops := map[string]*opInfo{} + paths, _ := spec["paths"].(yml) + for pathKey, pathVal := range paths { + pathItem, ok := pathVal.(yml) + if !ok { + continue + } + for method, mVal := range pathItem { + op, ok := mVal.(yml) + if !ok { + continue + } + opID, _ := op["operationId"].(string) + if opID == "" { + continue + } + info := &opInfo{ + OperationID: opID, + Method: strings.ToUpper(method), + Path: pathKey, + } + if s, ok := op["summary"].(string); ok { + info.Summary = strings.TrimSpace(s) + } + if d, ok := op["description"].(string); ok { + info.Description = strings.TrimSpace(d) + } + if tags, ok := op["tags"].([]interface{}); ok && len(tags) > 0 { + if t, ok := tags[0].(string); ok { + info.Tag = t + } + } + ops[opID] = info + } + } + return ops, nil +} + +func goFuncNamesForOp(opID string) []string { + base := upperFirst(opID) + return []string{ + base, + base + "WithBody", + base + "WithResponse", + base + "WithBodyWithResponse", + } +} + +func upperFirst(s string) string { + if s == "" { + return s + } + r := []rune(s) + r[0] = unicode.ToUpper(r[0]) + return string(r) +} + +type funcSite struct { + decl *ast.FuncDecl + op *opInfo +} + +type ifaceSite struct { + field *ast.Field + op *opInfo +} + +type docPatch struct { + startLine int // 1-indexed, inclusive + endLine int // 1-indexed, exclusive (the line of the decl itself) + lines []string +} + +// parses path, finds methods that resolve to exactly one OpenAPI +// operation, and rewrites doc comments above those methods and any matching +// interface method declarations in the same file. Returns true if the file was +// modified. +func annotateFile(path string, funcToOp map[string]*opInfo) (bool, error) { + src, err := os.ReadFile(path) + if err != nil { + return false, err + } + + fset := token.NewFileSet() + file, err := parser.ParseFile(fset, path, src, parser.ParseComments) + if err != nil { + return false, err + } + + sites, methodOp := collectMethodSites(file, funcToOp) + ifaceSites := collectInterfaceSites(file, methodOp) + + if len(sites) == 0 && len(ifaceSites) == 0 { + return false, nil + } + + patches := buildPatches(fset, sites, ifaceSites) + out, err := applyPatches(src, patches) + if err != nil { + return false, err + } + if string(out) == string(src) { + return false, nil + } + + info, err := os.Stat(path) + if err != nil { + return false, err + } + // #nosec G703 it's not an external file + if err := os.WriteFile(path, out, info.Mode().Perm()); err != nil { + return false, err + } + + return true, nil +} + +// collectMethodSites returns the set of method declarations that resolve to a +// unique OpenAPI operation, along with a map from method name to its op. The +// map drops names that resolve to different ops across receivers so the +// interface-side annotation pass can skip ambiguous matches. +func collectMethodSites(file *ast.File, funcToOp map[string]*opInfo) ([]funcSite, map[string]*opInfo) { + sites := make([]funcSite, 0, len(file.Decls)) + methodOp := map[string]*opInfo{} + for _, decl := range file.Decls { + fn, ok := decl.(*ast.FuncDecl) + if !ok || fn.Recv == nil || fn.Body == nil { + continue + } + op := uniqueAPIOp(fn.Body, funcToOp) + if op == nil { + continue + } + sites = append(sites, funcSite{decl: fn, op: op}) + if existing, dup := methodOp[fn.Name.Name]; dup && existing != op { + methodOp[fn.Name.Name] = nil + } else if !dup { + methodOp[fn.Name.Name] = op + } + } + return sites, methodOp +} + +// collectInterfaceSites returns interface method fields whose name matches an +// impl method in methodOp, so they can be annotated with the same doc. +func collectInterfaceSites(file *ast.File, methodOp map[string]*opInfo) []ifaceSite { + sites := make([]ifaceSite, 0, len(methodOp)) + for _, decl := range file.Decls { + gd, ok := decl.(*ast.GenDecl) + if !ok || gd.Tok != token.TYPE { + continue + } + for _, spec := range gd.Specs { + ts, ok := spec.(*ast.TypeSpec) + if !ok { + continue + } + it, ok := ts.Type.(*ast.InterfaceType) + if !ok || it.Methods == nil { + continue + } + for _, field := range it.Methods.List { + if len(field.Names) != 1 { + continue + } + op := methodOp[field.Names[0].Name] + if op == nil { + continue + } + sites = append(sites, ifaceSite{field: field, op: op}) + } + } + } + return sites +} + +// buildPatches converts func and interface sites into ordered docPatches, +// sorted by descending start line so applying them keeps earlier line numbers +// valid. +func buildPatches(fset *token.FileSet, sites []funcSite, ifaceSites []ifaceSite) []docPatch { + patches := make([]docPatch, 0, len(sites)+len(ifaceSites)) + for _, s := range sites { + startLine, endLine, indent := commentSpan(fset, s.decl.Pos(), s.decl.Doc) + patches = append(patches, docPatch{ + startLine: startLine, + endLine: endLine, + lines: renderDoc(s.decl.Name.Name, s.op, indent), + }) + } + for _, s := range ifaceSites { + startLine, endLine, indent := commentSpan(fset, s.field.Pos(), s.field.Doc) + patches = append(patches, docPatch{ + startLine: startLine, + endLine: endLine, + lines: renderDoc(s.field.Names[0].Name, s.op, indent), + }) + } + sort.Slice(patches, func(i, j int) bool { return patches[i].startLine > patches[j].startLine }) + return patches +} + +// applyPatches rewrites src by replacing the [startLine, endLine) range of each +// patch with its rendered lines. Patches must already be sorted in descending +// startLine order. +func applyPatches(src []byte, patches []docPatch) ([]byte, error) { + lines := strings.Split(string(src), "\n") + for _, p := range patches { + s := p.startLine - 1 + e := p.endLine - 1 + if s < 0 || e > len(lines) || s > e { + return nil, fmt.Errorf("patch out of bounds: start=%d end=%d total=%d", p.startLine, p.endLine, len(lines)) + } + lines = append(lines[:s], append(append([]string{}, p.lines...), lines[e:]...)...) + } + return []byte(strings.Join(lines, "\n")), nil +} + +// returns the OpenAPI operation that a function body calls iff it +// contains exactly one apiClient.(...) call where maps to a known +// operation. Returns nil otherwise (zero matches, multiple matches, or +// ambiguous matches). +func uniqueAPIOp(body *ast.BlockStmt, funcToOp map[string]*opInfo) *opInfo { + var found *opInfo + multiple := false + ast.Inspect(body, func(n ast.Node) bool { + if multiple { + return false + } + call, ok := n.(*ast.CallExpr) + if !ok { + return true + } + sel, ok := call.Fun.(*ast.SelectorExpr) + if !ok { + return true + } + // Match .apiClient.(...) + inner, ok := sel.X.(*ast.SelectorExpr) + if !ok || inner.Sel.Name != "apiClient" { + return true + } + op, ok := funcToOp[sel.Sel.Name] + if !ok { + return true + } + if found != nil && found != op { + multiple = true + return false + } + found = op + return true + }) + if multiple { + return nil + } + return found +} + +// returns the [startLine, endLine) range of lines that should be +// replaced for a declaration, and the leading whitespace indent on the decl +// line. startLine equals the line of an existing doc comment (if any) or the +// decl line itself when no doc is present. endLine is always the decl line. +func commentSpan(fset *token.FileSet, declPos token.Pos, doc *ast.CommentGroup) (int, int, string) { + declLine := fset.Position(declPos).Line + startLine := declLine + if doc != nil { + startLine = fset.Position(doc.Pos()).Line + } + // Read the decl line text to figure out indentation. + indent := "" + col := fset.Position(declPos).Column - 1 + if col > 0 { + indent = strings.Repeat(" ", col) + } + return startLine, declLine, indent +} + +func renderDoc(_ string, op *opInfo, indent string) []string { + var lines []string + + summary := firstSentence(op.Summary) + if summary == "" { + summary = firstSentence(op.Description) + } + if summary != "" { + lines = append(lines, indent+"// "+ensureTrailingPeriod(upperFirst(summary))) + } + + // include the full description only when it adds information beyond the summary. + if op.Description != "" && !strings.EqualFold(strings.TrimSpace(op.Description), strings.TrimSpace(op.Summary)) { + desc := strings.TrimSpace(op.Description) + if firstSentence(desc) != firstSentence(op.Summary) { + lines = append(lines, indent+"//") + for _, l := range strings.Split(desc, "\n") { + l = strings.TrimRight(l, " \t") + if l == "" { + lines = append(lines, indent+"//") + } else { + lines = append(lines, indent+"// "+l) + } + } + } + } + + lines = append(lines, indent+"//") + lines = append(lines, indent+fmt.Sprintf("// HTTP: %s %s", op.Method, op.Path)) + + if section := tagToDocs[op.Tag]; section != "" { + lines = append(lines, indent+"//") + lines = append(lines, indent+"// See: "+docsBaseURL+section) + } + + return lines +} + +func firstSentence(s string) string { + s = strings.TrimSpace(s) + if s == "" { + return "" + } + // take everything up to the first newline, that's usually the lead sentence. + if idx := strings.IndexByte(s, '\n'); idx >= 0 { + s = s[:idx] + } + return strings.TrimSpace(s) +} + +func ensureTrailingPeriod(s string) string { + if s == "" { + return s + } + if strings.HasSuffix(s, ".") || strings.HasSuffix(s, "?") || strings.HasSuffix(s, "!") { + return s + } + return s + "." +} diff --git a/typesense/api/generator/main.go b/typesense/api/generator/main.go index 0e3cc38f..62037fff 100644 --- a/typesense/api/generator/main.go +++ b/typesense/api/generator/main.go @@ -27,7 +27,7 @@ type MapKV struct { } func sortedSlice(params map[string]interface{}) []MapKV { - kvs := []MapKV{} + kvs := make([]MapKV, 0, len(params)) for k, v := range params { kvs = append(kvs, MapKV{k, v}) @@ -55,6 +55,7 @@ func main() { processOpenAPISpec(&m) writeGeneratorFile(&m) generateClient() + injectWrapperDocs("./typesense/api/generator/openapi.yml", "./typesense") log.Println("Successfully Completed !") } diff --git a/typesense/api_call.go b/typesense/api_call.go index 1dcf03de..9ad70f44 100644 --- a/typesense/api_call.go +++ b/typesense/api_call.go @@ -47,12 +47,16 @@ func NewAPICall(client circuit.HTTPRequestDoer, config *ClientConfig) *APICall { retryInterval: config.RetryInterval, } - // default numRetries is the number of nodes (+1 if nearestNode is specified) + // default numRetries is the number of nodes (+1 if nearestNode is specified), + // and falls back to 3. if config.NumRetries == 0 { apiCall.numRetriesPerRequest = len(config.Nodes) if config.NearestNode != "" { apiCall.numRetriesPerRequest++ } + if apiCall.numRetriesPerRequest == 0 { + apiCall.numRetriesPerRequest = 3 + } } apiCall.initializeNodesMetadata(config) diff --git a/typesense/client.go b/typesense/client.go index 29fdbbf4..d6b80c77 100644 --- a/typesense/client.go +++ b/typesense/client.go @@ -18,108 +18,197 @@ type APIClientInterface interface { } type Client struct { - apiConfig *ClientConfig - apiClient APIClientInterface - collections CollectionsInterface - aliases AliasesInterface + apiConfig *ClientConfig + apiClient APIClientInterface + collections CollectionsInterface + aliases AliasesInterface + // MultiSearch sends multiple search requests in a single HTTP request, + // avoiding the round-trip latency of issuing them separately. Also + // supports federated search across multiple collections. + // + // See: https://typesense.org/docs/latest/api/federated-multi-search.html MultiSearch MultiSearchInterface synonymSets SynonymSetsInterface curationSets CurationSetsInterface } +// Collections manages collections in the Typesense cluster. A collection is +// defined by a schema and holds the documents you search against. +// +// See: https://typesense.org/docs/latest/api/collections.html func (c *Client) Collections() CollectionsInterface { return c.collections } +// GenericCollection returns a handle for a single collection whose documents +// deserialize into T. Use this when you want to work with a typed Go struct +// instead of map[string]any. +// +// See: https://typesense.org/docs/latest/api/collections.html func GenericCollection[T any](c *Client, collectionName string) CollectionInterface[T] { return &collection[T]{apiClient: c.apiClient, name: collectionName} } +// Collection returns a handle for the collection with the given name. Use +// the returned interface to retrieve, update, or delete the collection, and +// to access its documents. +// +// See: https://typesense.org/docs/latest/api/collections.html func (c *Client) Collection(collectionName string) CollectionInterface[map[string]any] { return GenericCollection[map[string]any](c, collectionName) } +// Aliases manages collection aliases. An alias is a virtual name that points +// to a real collection, useful for zero-downtime reindexing. +// +// See: https://typesense.org/docs/latest/api/collection-alias.html func (c *Client) Aliases() AliasesInterface { return c.aliases } +// Alias returns a handle for the alias with the given name. +// +// See: https://typesense.org/docs/latest/api/collection-alias.html func (c *Client) Alias(aliasName string) AliasInterface { return &alias{apiClient: c.apiClient, name: aliasName} } +// Analytics manages analytics rules and events. Typesense can aggregate +// search queries for analytics purposes and query suggestions. +// +// See: https://typesense.org/docs/latest/api/analytics-query-suggestions.html func (c *Client) Analytics() AnalyticsInterface { return &analytics{apiClient: c.apiClient} } +// Stemming manages stemming dictionaries used during indexing and search. +// +// See: https://typesense.org/docs/latest/api/stemming.html func (c *Client) Stemming() StemmingInterface { return &stemming{apiClient: c.apiClient} } +// Conversations manages conversational search (RAG) models and history. +// +// See: https://typesense.org/docs/latest/api/conversational-search-rag.html func (c *Client) Conversations() ConversationsInterface { return &conversations{apiClient: c.apiClient} } +// Keys manages API keys with fine-grain access control. +// +// See: https://typesense.org/docs/latest/api/api-keys.html func (c *Client) Keys() KeysInterface { return &keys{apiClient: c.apiClient} } +// Key returns a handle for the API key with the given id. +// +// See: https://typesense.org/docs/latest/api/api-keys.html func (c *Client) Key(keyID int64) KeyInterface { return &key{apiClient: c.apiClient, keyID: keyID} } +// Operations exposes cluster-level operations: snapshots, leader votes, +// on-disk compaction, cache clearing, and toggling the slow-request log. +// +// See: https://typesense.org/docs/latest/api/cluster-operations.html func (c *Client) Operations() OperationsInterface { return &operations{apiClient: c.apiClient} } +// Presets manages stored search-parameter presets that can be referenced by +// name in subsequent search requests. +// +// See: https://typesense.org/docs/latest/api/search.html#presets func (c *Client) Presets() PresetsInterface { return &presets{apiClient: c.apiClient} } +// Preset returns a handle for the preset with the given name. +// +// See: https://typesense.org/docs/latest/api/search.html#presets func (c *Client) Preset(presetName string) PresetInterface { return &preset{apiClient: c.apiClient, presetName: presetName} } +// NLSearchModels manages natural-language search models. +// +// See: https://typesense.org/docs/latest/api/natural-language-search.html func (c *Client) NLSearchModels() NLSearchModelsInterface { return &nlSearchModels{apiClient: c.apiClient} } +// NLSearchModel returns a handle for the NL search model with the given id. +// +// See: https://typesense.org/docs/latest/api/natural-language-search.html func (c *Client) NLSearchModel(modelID string) NLSearchModelInterface { return &nlSearchModel{apiClient: c.apiClient, modelID: modelID} } +// SynonymSets manages synonym sets shared across collections. +// +// See: https://typesense.org/docs/latest/api/synonyms.html func (c *Client) SynonymSets() SynonymSetsInterface { return c.synonymSets } +// SynonymSet returns a handle for the synonym set with the given name. +// +// See: https://typesense.org/docs/latest/api/synonyms.html func (c *Client) SynonymSet(synonymSetName string) SynonymSetInterface { return &synonymSet{apiClient: c.apiClient, synonymSetName: synonymSetName} } +// CurationSets manages curation sets that override or boost results for +// specific queries. +// +// See: https://typesense.org/docs/latest/api/curation.html func (c *Client) CurationSets() CurationSetsInterface { return c.curationSets } +// CurationSet returns a handle for the curation set with the given name. +// +// See: https://typesense.org/docs/latest/api/curation.html func (c *Client) CurationSet(curationSetName string) CurationSetInterface { return &curationSet{apiClient: c.apiClient, curationSetName: curationSetName} } +// Stopwords manages stopword sets used to filter out common terms during +// indexing and search. +// +// See: https://typesense.org/docs/latest/api/stopwords.html func (c *Client) Stopwords() StopwordsInterface { return &stopwords{apiClient: c.apiClient} } +// Stopword returns a handle for the stopword set with the given id. +// +// See: https://typesense.org/docs/latest/api/stopwords.html func (c *Client) Stopword(stopwordsSetId string) StopwordInterface { return &stopword{apiClient: c.apiClient, stopwordsSetId: stopwordsSetId} } +// Stats returns the cluster API stats endpoint (request counts and latencies). +// +// See: https://typesense.org/docs/latest/api/cluster-operations.html#api-stats func (c *Client) Stats() StatsInterface { return &stats{apiClient: c.apiClient} } +// Metrics returns the cluster metrics endpoint (CPU, memory, disk usage). +// +// See: https://typesense.org/docs/latest/api/cluster-operations.html#cluster-metrics func (c *Client) Metrics() MetricsInterface { return &metrics{apiClient: c.apiClient} } -// Debug retrieves debug information from the Typesense server +// Print debugging information. +// +// HTTP: GET /debug +// +// See: https://typesense.org/docs/latest/api/cluster-operations.html#debug func (c *Client) Debug(ctx context.Context) (*api.DebugResponse, error) { return c.apiClient.DebugWithResponse(ctx) } diff --git a/typesense/collection.go b/typesense/collection.go index 97797cf9..fdd7318e 100644 --- a/typesense/collection.go +++ b/typesense/collection.go @@ -8,11 +8,32 @@ import ( // CollectionInterface is a type for Collection API operations type CollectionInterface[T any] interface { + // Retrieve a single collection. + // + // Retrieve the details of a collection, given its name. + // + // HTTP: GET /collections/{collectionName} + // + // See: https://typesense.org/docs/latest/api/collections.html Retrieve(ctx context.Context) (*api.CollectionResponse, error) + // Delete a collection. + // + // Permanently drops a collection. This action cannot be undone. For large collections, this might have an impact on read latencies. + // + // HTTP: DELETE /collections/{collectionName} + // + // See: https://typesense.org/docs/latest/api/collections.html Delete(ctx context.Context) (*api.CollectionResponse, error) Documents() DocumentsInterface Document(documentID string) DocumentInterface[T] + // Update a collection. + // + // Update a collection's schema to modify the fields and their types. + // + // HTTP: PATCH /collections/{collectionName} + // + // See: https://typesense.org/docs/latest/api/collections.html Update(context.Context, *api.CollectionUpdateSchema) (*api.CollectionUpdateSchema, error) } @@ -24,6 +45,13 @@ type collection[T any] struct { name string } +// Retrieve a single collection. +// +// Retrieve the details of a collection, given its name. +// +// HTTP: GET /collections/{collectionName} +// +// See: https://typesense.org/docs/latest/api/collections.html func (c *collection[T]) Retrieve(ctx context.Context) (*api.CollectionResponse, error) { response, err := c.apiClient.GetCollectionWithResponse(ctx, c.name) if err != nil { @@ -35,6 +63,13 @@ func (c *collection[T]) Retrieve(ctx context.Context) (*api.CollectionResponse, return response.JSON200, nil } +// Delete a collection. +// +// Permanently drops a collection. This action cannot be undone. For large collections, this might have an impact on read latencies. +// +// HTTP: DELETE /collections/{collectionName} +// +// See: https://typesense.org/docs/latest/api/collections.html func (c *collection[T]) Delete(ctx context.Context) (*api.CollectionResponse, error) { response, err := c.apiClient.DeleteCollectionWithResponse(ctx, c.name) if err != nil { @@ -54,6 +89,13 @@ func (c *collection[T]) Document(documentID string) DocumentInterface[T] { return &document[T]{apiClient: c.apiClient, collectionName: c.name, documentID: documentID} } +// Update a collection. +// +// Update a collection's schema to modify the fields and their types. +// +// HTTP: PATCH /collections/{collectionName} +// +// See: https://typesense.org/docs/latest/api/collections.html func (c *collection[T]) Update(ctx context.Context, schema *api.CollectionUpdateSchema) (*api.CollectionUpdateSchema, error) { response, err := c.apiClient.UpdateCollectionWithResponse(ctx, c.name, api.UpdateCollectionJSONRequestBody(*schema)) diff --git a/typesense/collections.go b/typesense/collections.go index 3652675d..b7234e52 100644 --- a/typesense/collections.go +++ b/typesense/collections.go @@ -8,7 +8,21 @@ import ( // CollectionsInterface is a type for Collections API operations type CollectionsInterface interface { + // Create a new collection. + // + // When a collection is created, we give it a name and describe the fields that will be indexed from the documents added to the collection. + // + // HTTP: POST /collections + // + // See: https://typesense.org/docs/latest/api/collections.html Create(ctx context.Context, schema *api.CollectionSchema) (*api.CollectionResponse, error) + // List all collections. + // + // Returns a summary of all your collections. The collections are returned sorted by creation date, with the most recent collections appearing first. + // + // HTTP: GET /collections + // + // See: https://typesense.org/docs/latest/api/collections.html Retrieve(ctx context.Context, params *api.GetCollectionsParams) ([]*api.CollectionResponse, error) } @@ -17,6 +31,13 @@ type collections struct { apiClient APIClientInterface } +// Create a new collection. +// +// When a collection is created, we give it a name and describe the fields that will be indexed from the documents added to the collection. +// +// HTTP: POST /collections +// +// See: https://typesense.org/docs/latest/api/collections.html func (c *collections) Create(ctx context.Context, schema *api.CollectionSchema) (*api.CollectionResponse, error) { response, err := c.apiClient.CreateCollectionWithResponse(ctx, api.CreateCollectionJSONRequestBody(*schema)) @@ -29,6 +50,13 @@ func (c *collections) Create(ctx context.Context, schema *api.CollectionSchema) return response.JSON201, nil } +// List all collections. +// +// Returns a summary of all your collections. The collections are returned sorted by creation date, with the most recent collections appearing first. +// +// HTTP: GET /collections +// +// See: https://typesense.org/docs/latest/api/collections.html func (c *collections) Retrieve(ctx context.Context, params *api.GetCollectionsParams) ([]*api.CollectionResponse, error) { response, err := c.apiClient.GetCollectionsWithResponse(ctx, params) if err != nil { diff --git a/typesense/conversation_model.go b/typesense/conversation_model.go index 88880a4f..8fb97411 100644 --- a/typesense/conversation_model.go +++ b/typesense/conversation_model.go @@ -7,8 +7,23 @@ import ( ) type ConversationModelInterface interface { + // Retrieve a conversation model. + // + // HTTP: GET /conversations/models/{modelId} + // + // See: https://typesense.org/docs/latest/api/conversational-search-rag.html Retrieve(ctx context.Context) (*api.ConversationModelSchema, error) + // Update a conversation model. + // + // HTTP: PUT /conversations/models/{modelId} + // + // See: https://typesense.org/docs/latest/api/conversational-search-rag.html Update(ctx context.Context, schema *api.ConversationModelUpdateSchema) (*api.ConversationModelSchema, error) + // Delete a conversation model. + // + // HTTP: DELETE /conversations/models/{modelId} + // + // See: https://typesense.org/docs/latest/api/conversational-search-rag.html Delete(ctx context.Context) (*api.ConversationModelSchema, error) } @@ -17,6 +32,11 @@ type conversationModel struct { modelId string } +// Retrieve a conversation model. +// +// HTTP: GET /conversations/models/{modelId} +// +// See: https://typesense.org/docs/latest/api/conversational-search-rag.html func (c *conversationModel) Retrieve(ctx context.Context) (*api.ConversationModelSchema, error) { response, err := c.apiClient.RetrieveConversationModelWithResponse(ctx, c.modelId) if err != nil { @@ -28,6 +48,11 @@ func (c *conversationModel) Retrieve(ctx context.Context) (*api.ConversationMode return response.JSON200, nil } +// Update a conversation model. +// +// HTTP: PUT /conversations/models/{modelId} +// +// See: https://typesense.org/docs/latest/api/conversational-search-rag.html func (c *conversationModel) Update(ctx context.Context, schema *api.ConversationModelUpdateSchema) (*api.ConversationModelSchema, error) { response, err := c.apiClient.UpdateConversationModelWithResponse(ctx, c.modelId, api.UpdateConversationModelJSONRequestBody(*schema)) if err != nil { @@ -39,6 +64,11 @@ func (c *conversationModel) Update(ctx context.Context, schema *api.Conversation return response.JSON200, nil } +// Delete a conversation model. +// +// HTTP: DELETE /conversations/models/{modelId} +// +// See: https://typesense.org/docs/latest/api/conversational-search-rag.html func (c *conversationModel) Delete(ctx context.Context) (*api.ConversationModelSchema, error) { response, err := c.apiClient.DeleteConversationModelWithResponse(ctx, c.modelId) if err != nil { diff --git a/typesense/conversation_models.go b/typesense/conversation_models.go index feca83df..82b635e1 100644 --- a/typesense/conversation_models.go +++ b/typesense/conversation_models.go @@ -8,7 +8,19 @@ import ( // ConversationModelsInterface is a type for ConversationModels API operations type ConversationModelsInterface interface { + // Create a conversation model. + // + // HTTP: POST /conversations/models + // + // See: https://typesense.org/docs/latest/api/conversational-search-rag.html Create(ctx context.Context, schema *api.ConversationModelCreateSchema) (*api.ConversationModelSchema, error) + // List all conversation models. + // + // Retrieve all conversation models + // + // HTTP: GET /conversations/models + // + // See: https://typesense.org/docs/latest/api/conversational-search-rag.html Retrieve(ctx context.Context) ([]*api.ConversationModelSchema, error) } @@ -17,6 +29,11 @@ type conversationModels struct { apiClient APIClientInterface } +// Create a conversation model. +// +// HTTP: POST /conversations/models +// +// See: https://typesense.org/docs/latest/api/conversational-search-rag.html func (c *conversationModels) Create(ctx context.Context, schema *api.ConversationModelCreateSchema) (*api.ConversationModelSchema, error) { response, err := c.apiClient.CreateConversationModelWithResponse(ctx, api.CreateConversationModelJSONRequestBody(*schema)) if err != nil { @@ -28,6 +45,13 @@ func (c *conversationModels) Create(ctx context.Context, schema *api.Conversatio return response.JSON201, nil } +// List all conversation models. +// +// # Retrieve all conversation models +// +// HTTP: GET /conversations/models +// +// See: https://typesense.org/docs/latest/api/conversational-search-rag.html func (c *conversationModels) Retrieve(ctx context.Context) ([]*api.ConversationModelSchema, error) { response, err := c.apiClient.RetrieveAllConversationModelsWithResponse(ctx) if err != nil { diff --git a/typesense/curation_set.go b/typesense/curation_set.go index a9c28a2a..da5679d4 100644 --- a/typesense/curation_set.go +++ b/typesense/curation_set.go @@ -8,11 +8,29 @@ import ( // CurationSetInterface is a type for individual Curation Set API operations type CurationSetInterface interface { - // Retrieve a single curation set + // Retrieve a curation set. + // + // Retrieve a specific curation set by its name + // + // HTTP: GET /curation_sets/{curationSetName} + // + // See: https://typesense.org/docs/latest/api/curation.html Retrieve(ctx context.Context) (*api.CurationSetSchema, error) - // Update a curation set + // Create or update a curation set. + // + // Create or update a curation set with the given name + // + // HTTP: PUT /curation_sets/{curationSetName} + // + // See: https://typesense.org/docs/latest/api/curation.html Upsert(ctx context.Context, curationSetSchema *api.CurationSetCreateSchema) (*api.CurationSetSchema, error) - // Delete a curation set + // Delete a curation set. + // + // Delete a specific curation set by its name + // + // HTTP: DELETE /curation_sets/{curationSetName} + // + // See: https://typesense.org/docs/latest/api/curation.html Delete(ctx context.Context) (*api.CurationSetDeleteSchema, error) } @@ -22,6 +40,13 @@ type curationSet struct { curationSetName string } +// Retrieve a curation set. +// +// # Retrieve a specific curation set by its name +// +// HTTP: GET /curation_sets/{curationSetName} +// +// See: https://typesense.org/docs/latest/api/curation.html func (c *curationSet) Retrieve(ctx context.Context) (*api.CurationSetSchema, error) { response, err := c.apiClient.RetrieveCurationSetWithResponse(ctx, c.curationSetName) if err != nil { @@ -33,6 +58,13 @@ func (c *curationSet) Retrieve(ctx context.Context) (*api.CurationSetSchema, err return response.JSON200, nil } +// Create or update a curation set. +// +// # Create or update a curation set with the given name +// +// HTTP: PUT /curation_sets/{curationSetName} +// +// See: https://typesense.org/docs/latest/api/curation.html func (c *curationSet) Upsert(ctx context.Context, curationSetSchema *api.CurationSetCreateSchema) (*api.CurationSetSchema, error) { response, err := c.apiClient.UpsertCurationSetWithResponse(ctx, c.curationSetName, api.UpsertCurationSetJSONRequestBody(*curationSetSchema)) if err != nil { @@ -44,6 +76,13 @@ func (c *curationSet) Upsert(ctx context.Context, curationSetSchema *api.Curatio return response.JSON200, nil } +// Delete a curation set. +// +// # Delete a specific curation set by its name +// +// HTTP: DELETE /curation_sets/{curationSetName} +// +// See: https://typesense.org/docs/latest/api/curation.html func (c *curationSet) Delete(ctx context.Context) (*api.CurationSetDeleteSchema, error) { response, err := c.apiClient.DeleteCurationSetWithResponse(ctx, c.curationSetName) if err != nil { diff --git a/typesense/curation_sets.go b/typesense/curation_sets.go index 9910c4a6..2e5c6dd9 100644 --- a/typesense/curation_sets.go +++ b/typesense/curation_sets.go @@ -10,9 +10,21 @@ import ( // CurationSetsInterface is a type for Curation Sets API operations type CurationSetsInterface interface { - // Create or update a curation set + // Create or update a curation set. + // + // Create or update a curation set with the given name + // + // HTTP: PUT /curation_sets/{curationSetName} + // + // See: https://typesense.org/docs/latest/api/curation.html Upsert(ctx context.Context, curationSetName string, curationSetSchema *api.CurationSetCreateSchema) (*api.CurationSetSchema, error) + // List all curation sets. + // // Retrieve all curation sets + // + // HTTP: GET /curation_sets + // + // See: https://typesense.org/docs/latest/api/curation.html Retrieve(ctx context.Context) ([]api.CurationSetSchema, error) } @@ -21,6 +33,13 @@ type curationSets struct { apiClient APIClientInterface } +// Create or update a curation set. +// +// # Create or update a curation set with the given name +// +// HTTP: PUT /curation_sets/{curationSetName} +// +// See: https://typesense.org/docs/latest/api/curation.html func (c *curationSets) Upsert(ctx context.Context, curationSetName string, curationSetSchema *api.CurationSetCreateSchema) (*api.CurationSetSchema, error) { response, err := c.apiClient.UpsertCurationSetWithResponse(ctx, curationSetName, api.UpsertCurationSetJSONRequestBody(*curationSetSchema)) if err != nil { @@ -32,6 +51,13 @@ func (c *curationSets) Upsert(ctx context.Context, curationSetName string, curat return response.JSON200, nil } +// List all curation sets. +// +// # Retrieve all curation sets +// +// HTTP: GET /curation_sets +// +// See: https://typesense.org/docs/latest/api/curation.html func (c *curationSets) Retrieve(ctx context.Context) ([]api.CurationSetSchema, error) { response, err := c.apiClient.RetrieveCurationSetsWithResponse(ctx) if err != nil { diff --git a/typesense/document.go b/typesense/document.go index e1e3e111..9071506d 100644 --- a/typesense/document.go +++ b/typesense/document.go @@ -10,8 +10,29 @@ import ( ) type DocumentInterface[T any] interface { + // Retrieve a document. + // + // Fetch an individual document from a collection by using its ID. + // + // HTTP: GET /collections/{collectionName}/documents/{documentId} + // + // See: https://typesense.org/docs/latest/api/documents.html Retrieve(ctx context.Context) (T, error) + // Update a document. + // + // Update an individual document from a collection by using its ID. The update can be partial. + // + // HTTP: PATCH /collections/{collectionName}/documents/{documentId} + // + // See: https://typesense.org/docs/latest/api/documents.html Update(ctx context.Context, document any, params *api.DocumentIndexParameters) (T, error) + // Delete a document. + // + // Delete an individual document from a collection by using its ID. + // + // HTTP: DELETE /collections/{collectionName}/documents/{documentId} + // + // See: https://typesense.org/docs/latest/api/documents.html Delete(ctx context.Context) (T, error) } @@ -23,6 +44,13 @@ type document[T any] struct { documentID string } +// Retrieve a document. +// +// Fetch an individual document from a collection by using its ID. +// +// HTTP: GET /collections/{collectionName}/documents/{documentId} +// +// See: https://typesense.org/docs/latest/api/documents.html func (d *document[T]) Retrieve(ctx context.Context) (resp T, err error) { response, err := d.apiClient.GetDocument(ctx, d.collectionName, d.documentID) @@ -41,6 +69,13 @@ func (d *document[T]) Retrieve(ctx context.Context) (resp T, err error) { return resp, nil } +// Update a document. +// +// Update an individual document from a collection by using its ID. The update can be partial. +// +// HTTP: PATCH /collections/{collectionName}/documents/{documentId} +// +// See: https://typesense.org/docs/latest/api/documents.html func (d *document[T]) Update(ctx context.Context, document any, params *api.DocumentIndexParameters) (resp T, err error) { response, err := d.apiClient.UpdateDocument(ctx, d.collectionName, d.documentID, &api.UpdateDocumentParams{DirtyValues: params.DirtyValues}, document) @@ -59,6 +94,13 @@ func (d *document[T]) Update(ctx context.Context, document any, params *api.Docu return resp, nil } +// Delete a document. +// +// Delete an individual document from a collection by using its ID. +// +// HTTP: DELETE /collections/{collectionName}/documents/{documentId} +// +// See: https://typesense.org/docs/latest/api/documents.html func (d *document[T]) Delete(ctx context.Context) (resp T, err error) { response, err := d.apiClient.DeleteDocument(ctx, d.collectionName, d.documentID) diff --git a/typesense/documents.go b/typesense/documents.go index 18e814a1..ff77f763 100644 --- a/typesense/documents.go +++ b/typesense/documents.go @@ -22,22 +22,50 @@ const ( type DocumentsInterface interface { // Create returns indexed document Create(ctx context.Context, document interface{}, params *api.DocumentIndexParameters) (map[string]interface{}, error) - // Update updates documents matching the filter_by condition + // Update documents with conditional query. + // + // The filter_by query parameter is used to filter to specify a condition against which the documents are matched. The request body contains the fields that should be updated for any documents that match the filter condition. This endpoint is only available if the Typesense server is version `0.25.0.rc12` or later. + // + // HTTP: PATCH /collections/{collectionName}/documents + // + // See: https://typesense.org/docs/latest/api/documents.html Update(ctx context.Context, updateFields interface{}, params *api.UpdateDocumentsParams) (int, error) // Upsert returns indexed/updated document Upsert(ctx context.Context, document interface{}, params *api.DocumentIndexParameters) (map[string]interface{}, error) - // Delete returns number of deleted documents + // Delete a bunch of documents. + // + // Delete a bunch of documents that match a specific filter condition. Use the `batch_size` parameter to control the number of documents that should deleted at a time. A larger value will speed up deletions, but will impact performance of other operations running on the server. + // + // HTTP: DELETE /collections/{collectionName}/documents + // + // See: https://typesense.org/docs/latest/api/documents.html Delete(ctx context.Context, filter *api.DeleteDocumentsParams) (int, error) - // Search performs document search in collection + // Search for documents in a collection. + // + // Search for documents in a collection that match the search criteria. + // + // HTTP: GET /collections/{collectionName}/documents/search + // + // See: https://typesense.org/docs/latest/api/documents.html Search(ctx context.Context, params *api.SearchCollectionParams) (*api.SearchResult, error) - // Export returns all documents from index in jsonl format + // Export all documents in a collection. + // + // Export all documents in a collection in JSON lines format. + // + // HTTP: GET /collections/{collectionName}/documents/export + // + // See: https://typesense.org/docs/latest/api/documents.html Export(ctx context.Context, params *api.ExportDocumentsParams) (io.ReadCloser, error) // Import returns json array. Each item of the response indicates // the result of each document present in the request body (in the same order). Import(ctx context.Context, documents []interface{}, params *api.ImportDocumentsParams) ([]*api.ImportDocumentResponse, error) - // ImportJsonl accepts documents and returns result in jsonl format. Each line of the - // response indicates the result of each document present in the - // request body (in the same order). + // Import documents into a collection. + // + // The documents to be imported must be formatted in a newline delimited JSON structure. You can feed the output file from a Typesense export operation directly as import. + // + // HTTP: POST /collections/{collectionName}/documents/import + // + // See: https://typesense.org/docs/latest/api/documents.html ImportJsonl(ctx context.Context, body io.Reader, params *api.ImportDocumentsParams) (io.ReadCloser, error) } @@ -47,6 +75,13 @@ type documents struct { collectionName string } +// Index a document. +// +// A document to be indexed in a given collection must conform to the schema of the collection. +// +// HTTP: POST /collections/{collectionName}/documents +// +// See: https://typesense.org/docs/latest/api/documents.html func (d *documents) indexDocument(ctx context.Context, document interface{}, params *api.IndexDocumentParams) (map[string]interface{}, error) { response, err := d.apiClient.IndexDocumentWithResponse(ctx, d.collectionName, params, document) @@ -63,6 +98,13 @@ func (d *documents) Create(ctx context.Context, document interface{}, params *ap return d.indexDocument(ctx, document, &api.IndexDocumentParams{DirtyValues: params.DirtyValues}) } +// Update documents with conditional query. +// +// The filter_by query parameter is used to filter to specify a condition against which the documents are matched. The request body contains the fields that should be updated for any documents that match the filter condition. This endpoint is only available if the Typesense server is version `0.25.0.rc12` or later. +// +// HTTP: PATCH /collections/{collectionName}/documents +// +// See: https://typesense.org/docs/latest/api/documents.html func (d *documents) Update(ctx context.Context, updateFields interface{}, params *api.UpdateDocumentsParams) (int, error) { response, err := d.apiClient.UpdateDocumentsWithResponse(ctx, d.collectionName, params, updateFields) @@ -79,6 +121,13 @@ func (d *documents) Upsert(ctx context.Context, document interface{}, params *ap return d.indexDocument(ctx, document, &api.IndexDocumentParams{Action: pointer.Any(api.Upsert), DirtyValues: params.DirtyValues}) } +// Delete a bunch of documents. +// +// Delete a bunch of documents that match a specific filter condition. Use the `batch_size` parameter to control the number of documents that should deleted at a time. A larger value will speed up deletions, but will impact performance of other operations running on the server. +// +// HTTP: DELETE /collections/{collectionName}/documents +// +// See: https://typesense.org/docs/latest/api/documents.html func (d *documents) Delete(ctx context.Context, filter *api.DeleteDocumentsParams) (int, error) { response, err := d.apiClient.DeleteDocumentsWithResponse(ctx, d.collectionName, filter) @@ -91,6 +140,13 @@ func (d *documents) Delete(ctx context.Context, filter *api.DeleteDocumentsParam return response.JSON200.NumDeleted, nil } +// Search for documents in a collection. +// +// Search for documents in a collection that match the search criteria. +// +// HTTP: GET /collections/{collectionName}/documents/search +// +// See: https://typesense.org/docs/latest/api/documents.html func (d *documents) Search(ctx context.Context, params *api.SearchCollectionParams) (*api.SearchResult, error) { response, err := d.apiClient.SearchCollectionWithResponse(ctx, d.collectionName, params) @@ -103,6 +159,13 @@ func (d *documents) Search(ctx context.Context, params *api.SearchCollectionPara return response.JSON200, nil } +// Export all documents in a collection. +// +// Export all documents in a collection in JSON lines format. +// +// HTTP: GET /collections/{collectionName}/documents/export +// +// See: https://typesense.org/docs/latest/api/documents.html func (d *documents) Export(ctx context.Context, params *api.ExportDocumentsParams) (io.ReadCloser, error) { response, err := d.apiClient.ExportDocuments(ctx, d.collectionName, params) if err != nil { @@ -159,6 +222,13 @@ func (d *documents) Import(ctx context.Context, documents []interface{}, params return result, scanner.Err() } +// Import documents into a collection. +// +// The documents to be imported must be formatted in a newline delimited JSON structure. You can feed the output file from a Typesense export operation directly as import. +// +// HTTP: POST /collections/{collectionName}/documents/import +// +// See: https://typesense.org/docs/latest/api/documents.html func (d *documents) ImportJsonl(ctx context.Context, body io.Reader, params *api.ImportDocumentsParams) (io.ReadCloser, error) { initImportParams(params) response, err := d.apiClient.ImportDocumentsWithBody(ctx, diff --git a/typesense/health.go b/typesense/health.go index 06607261..2a059e41 100644 --- a/typesense/health.go +++ b/typesense/health.go @@ -5,6 +5,11 @@ import ( "time" ) +// Checks if Typesense server is ready to accept requests. +// +// HTTP: GET /health +// +// See: https://typesense.org/docs/latest/api/cluster-operations.html#health func (c *Client) Health(ctx context.Context, timeout time.Duration) (bool, error) { ctx, cancel := context.WithTimeout(ctx, timeout) defer cancel() diff --git a/typesense/key.go b/typesense/key.go index 2ca3fbcf..e73a825b 100644 --- a/typesense/key.go +++ b/typesense/key.go @@ -7,7 +7,19 @@ import ( ) type KeyInterface interface { + // Retrieve (metadata about) a key. + // + // Retrieve (metadata about) a key. Only the key prefix is returned when you retrieve a key. Due to security reasons, only the create endpoint returns the full API key. + // + // HTTP: GET /keys/{keyId} + // + // See: https://typesense.org/docs/latest/api/api-keys.html Retrieve(ctx context.Context) (*api.ApiKey, error) + // Delete an API key given its ID. + // + // HTTP: DELETE /keys/{keyId} + // + // See: https://typesense.org/docs/latest/api/api-keys.html Delete(ctx context.Context) (*api.ApiKeyDeleteResponse, error) } @@ -16,6 +28,13 @@ type key struct { keyID int64 } +// Retrieve (metadata about) a key. +// +// Retrieve (metadata about) a key. Only the key prefix is returned when you retrieve a key. Due to security reasons, only the create endpoint returns the full API key. +// +// HTTP: GET /keys/{keyId} +// +// See: https://typesense.org/docs/latest/api/api-keys.html func (k *key) Retrieve(ctx context.Context) (*api.ApiKey, error) { response, err := k.apiClient.GetKeyWithResponse(ctx, k.keyID) if err != nil { @@ -27,6 +46,11 @@ func (k *key) Retrieve(ctx context.Context) (*api.ApiKey, error) { return response.JSON200, nil } +// Delete an API key given its ID. +// +// HTTP: DELETE /keys/{keyId} +// +// See: https://typesense.org/docs/latest/api/api-keys.html func (k *key) Delete(ctx context.Context) (*api.ApiKeyDeleteResponse, error) { response, err := k.apiClient.DeleteKeyWithResponse(ctx, k.keyID) if err != nil { diff --git a/typesense/keys.go b/typesense/keys.go index 6199c5b5..c9f9a0c0 100644 --- a/typesense/keys.go +++ b/typesense/keys.go @@ -12,7 +12,19 @@ import ( ) type KeysInterface interface { + // Create an API Key. + // + // Create an API Key with fine-grain access control. You can restrict access on both a per-collection and per-action level. The generated key is returned only during creation. You want to store this key carefully in a secure place. + // + // HTTP: POST /keys + // + // See: https://typesense.org/docs/latest/api/api-keys.html Create(context.Context, *api.ApiKeySchema) (*api.ApiKey, error) + // Retrieve (metadata about) all keys. + // + // HTTP: GET /keys + // + // See: https://typesense.org/docs/latest/api/api-keys.html Retrieve(context.Context) ([]*api.ApiKey, error) GenerateScopedSearchKey(searchKey string, params map[string]interface{}) (string, error) } @@ -21,6 +33,13 @@ type keys struct { apiClient APIClientInterface } +// Create an API Key. +// +// Create an API Key with fine-grain access control. You can restrict access on both a per-collection and per-action level. The generated key is returned only during creation. You want to store this key carefully in a secure place. +// +// HTTP: POST /keys +// +// See: https://typesense.org/docs/latest/api/api-keys.html func (k *keys) Create(ctx context.Context, key *api.ApiKeySchema) (*api.ApiKey, error) { response, err := k.apiClient.CreateKeyWithResponse(ctx, api.CreateKeyJSONRequestBody(*key)) @@ -33,6 +52,11 @@ func (k *keys) Create(ctx context.Context, key *api.ApiKeySchema) (*api.ApiKey, return response.JSON201, nil } +// Retrieve (metadata about) all keys. +// +// HTTP: GET /keys +// +// See: https://typesense.org/docs/latest/api/api-keys.html func (k *keys) Retrieve(ctx context.Context) ([]*api.ApiKey, error) { response, err := k.apiClient.GetKeysWithResponse(ctx) if err != nil { diff --git a/typesense/metrics.go b/typesense/metrics.go index 08e5ec79..d0f7b4a3 100644 --- a/typesense/metrics.go +++ b/typesense/metrics.go @@ -5,6 +5,13 @@ import ( ) type MetricsInterface interface { + // Get current RAM, CPU, Disk & Network usage metrics. + // + // Retrieve the metrics. + // + // HTTP: GET /metrics.json + // + // See: https://typesense.org/docs/latest/api/cluster-operations.html Retrieve(ctx context.Context) (map[string]interface{}, error) } @@ -12,6 +19,13 @@ type metrics struct { apiClient APIClientInterface } +// Get current RAM, CPU, Disk & Network usage metrics. +// +// Retrieve the metrics. +// +// HTTP: GET /metrics.json +// +// See: https://typesense.org/docs/latest/api/cluster-operations.html func (m *metrics) Retrieve(ctx context.Context) (map[string]interface{}, error) { response, err := m.apiClient.RetrieveMetricsWithResponse(ctx) if err != nil { diff --git a/typesense/multi_search.go b/typesense/multi_search.go index 19e1cf7c..ef21c3db 100644 --- a/typesense/multi_search.go +++ b/typesense/multi_search.go @@ -10,7 +10,21 @@ import ( ) type MultiSearchInterface interface { + // Send multiple search requests in a single HTTP request. + // + // This is especially useful to avoid round-trip network latencies incurred otherwise if each of these requests are sent in separate HTTP requests. You can also use this feature to do a federated search across multiple collections in a single HTTP request. + // + // HTTP: POST /multi_search + // + // See: https://typesense.org/docs/latest/api/documents.html Perform(ctx context.Context, commonSearchParams *api.MultiSearchParams, searchParams api.MultiSearchSearchesParameter) (*api.MultiSearchResult, error) + // Send multiple search requests in a single HTTP request. + // + // This is especially useful to avoid round-trip network latencies incurred otherwise if each of these requests are sent in separate HTTP requests. You can also use this feature to do a federated search across multiple collections in a single HTTP request. + // + // HTTP: POST /multi_search + // + // See: https://typesense.org/docs/latest/api/documents.html PerformWithContentType(ctx context.Context, commonSearchParams *api.MultiSearchParams, searchParams api.MultiSearchSearchesParameter, contentType string) (*api.MultiSearchResponse, error) } @@ -18,6 +32,13 @@ type multiSearch struct { apiClient APIClientInterface } +// Send multiple search requests in a single HTTP request. +// +// This is especially useful to avoid round-trip network latencies incurred otherwise if each of these requests are sent in separate HTTP requests. You can also use this feature to do a federated search across multiple collections in a single HTTP request. +// +// HTTP: POST /multi_search +// +// See: https://typesense.org/docs/latest/api/documents.html func (m *multiSearch) Perform(ctx context.Context, commonSearchParams *api.MultiSearchParams, searchParams api.MultiSearchSearchesParameter) (*api.MultiSearchResult, error) { response, err := m.apiClient.MultiSearchWithResponse(ctx, commonSearchParams, api.MultiSearchJSONRequestBody(searchParams)) if err != nil { @@ -29,6 +50,13 @@ func (m *multiSearch) Perform(ctx context.Context, commonSearchParams *api.Multi return response.JSON200, nil } +// Send multiple search requests in a single HTTP request. +// +// This is especially useful to avoid round-trip network latencies incurred otherwise if each of these requests are sent in separate HTTP requests. You can also use this feature to do a federated search across multiple collections in a single HTTP request. +// +// HTTP: POST /multi_search +// +// See: https://typesense.org/docs/latest/api/documents.html func (m *multiSearch) PerformWithContentType(ctx context.Context, commonSearchParams *api.MultiSearchParams, searchParams api.MultiSearchSearchesParameter, contentType string) (*api.MultiSearchResponse, error) { body := api.MultiSearchJSONRequestBody(searchParams) var requestReader io.Reader diff --git a/typesense/nl_search_model.go b/typesense/nl_search_model.go index 9bb580b6..727d511c 100644 --- a/typesense/nl_search_model.go +++ b/typesense/nl_search_model.go @@ -7,8 +7,29 @@ import ( ) type NLSearchModelInterface interface { + // Retrieve a NL search model. + // + // Retrieve a specific NL search model by its ID. + // + // HTTP: GET /nl_search_models/{modelId} + // + // See: https://typesense.org/docs/latest/api/natural-language-search.html Retrieve(ctx context.Context) (*api.NLSearchModelSchema, error) + // Update a NL search model. + // + // Update an existing NL search model. + // + // HTTP: PUT /nl_search_models/{modelId} + // + // See: https://typesense.org/docs/latest/api/natural-language-search.html Update(ctx context.Context, model *api.NLSearchModelUpdateSchema) (*api.NLSearchModelSchema, error) + // Delete a NL search model. + // + // Delete a specific NL search model by its ID. + // + // HTTP: DELETE /nl_search_models/{modelId} + // + // See: https://typesense.org/docs/latest/api/natural-language-search.html Delete(ctx context.Context) (*api.NLSearchModelDeleteSchema, error) } @@ -17,6 +38,13 @@ type nlSearchModel struct { modelID string } +// Retrieve a NL search model. +// +// Retrieve a specific NL search model by its ID. +// +// HTTP: GET /nl_search_models/{modelId} +// +// See: https://typesense.org/docs/latest/api/natural-language-search.html func (n *nlSearchModel) Retrieve(ctx context.Context) (*api.NLSearchModelSchema, error) { response, err := n.apiClient.RetrieveNLSearchModelWithResponse(ctx, n.modelID) if err != nil { @@ -28,6 +56,13 @@ func (n *nlSearchModel) Retrieve(ctx context.Context) (*api.NLSearchModelSchema, return response.JSON200, nil } +// Update a NL search model. +// +// Update an existing NL search model. +// +// HTTP: PUT /nl_search_models/{modelId} +// +// See: https://typesense.org/docs/latest/api/natural-language-search.html func (n *nlSearchModel) Update(ctx context.Context, model *api.NLSearchModelUpdateSchema) (*api.NLSearchModelSchema, error) { response, err := n.apiClient.UpdateNLSearchModelWithResponse(ctx, n.modelID, *model) if err != nil { @@ -39,6 +74,13 @@ func (n *nlSearchModel) Update(ctx context.Context, model *api.NLSearchModelUpda return response.JSON200, nil } +// Delete a NL search model. +// +// Delete a specific NL search model by its ID. +// +// HTTP: DELETE /nl_search_models/{modelId} +// +// See: https://typesense.org/docs/latest/api/natural-language-search.html func (n *nlSearchModel) Delete(ctx context.Context) (*api.NLSearchModelDeleteSchema, error) { response, err := n.apiClient.DeleteNLSearchModelWithResponse(ctx, n.modelID) if err != nil { diff --git a/typesense/nl_search_models.go b/typesense/nl_search_models.go index 16619d81..a25f2e52 100644 --- a/typesense/nl_search_models.go +++ b/typesense/nl_search_models.go @@ -7,7 +7,21 @@ import ( ) type NLSearchModelsInterface interface { + // List all NL search models. + // + // Retrieve all NL search models. + // + // HTTP: GET /nl_search_models + // + // See: https://typesense.org/docs/latest/api/natural-language-search.html Retrieve(ctx context.Context) ([]*api.NLSearchModelSchema, error) + // Create a NL search model. + // + // Create a new NL search model. + // + // HTTP: POST /nl_search_models + // + // See: https://typesense.org/docs/latest/api/natural-language-search.html Create(ctx context.Context, model *api.NLSearchModelCreateSchema) (*api.NLSearchModelSchema, error) } @@ -15,6 +29,13 @@ type nlSearchModels struct { apiClient APIClientInterface } +// List all NL search models. +// +// Retrieve all NL search models. +// +// HTTP: GET /nl_search_models +// +// See: https://typesense.org/docs/latest/api/natural-language-search.html func (n *nlSearchModels) Retrieve(ctx context.Context) ([]*api.NLSearchModelSchema, error) { response, err := n.apiClient.RetrieveAllNLSearchModelsWithResponse(ctx) if err != nil { @@ -33,6 +54,13 @@ func (n *nlSearchModels) Retrieve(ctx context.Context) ([]*api.NLSearchModelSche return result, nil } +// Create a NL search model. +// +// Create a new NL search model. +// +// HTTP: POST /nl_search_models +// +// See: https://typesense.org/docs/latest/api/natural-language-search.html func (n *nlSearchModels) Create(ctx context.Context, model *api.NLSearchModelCreateSchema) (*api.NLSearchModelSchema, error) { response, err := n.apiClient.CreateNLSearchModelWithResponse(ctx, *model) if err != nil { diff --git a/typesense/operations.go b/typesense/operations.go index f33553d1..9092e2d9 100644 --- a/typesense/operations.go +++ b/typesense/operations.go @@ -7,7 +7,21 @@ import ( ) type OperationsInterface interface { + // Creates a point-in-time snapshot of a Typesense node's state and data in the specified directory. + // + // Creates a point-in-time snapshot of a Typesense node's state and data in the specified directory. You can then backup the snapshot directory that gets created and later restore it as a data directory, as needed. + // + // HTTP: POST /operations/snapshot + // + // See: https://typesense.org/docs/latest/api/cluster-operations.html Snapshot(ctx context.Context, snapshotPath string) (bool, error) + // Triggers a follower node to initiate the raft voting process, which triggers leader re-election. + // + // Triggers a follower node to initiate the raft voting process, which triggers leader re-election. The follower node that you run this operation against will become the new leader, once this command succeeds. + // + // HTTP: POST /operations/vote + // + // See: https://typesense.org/docs/latest/api/cluster-operations.html Vote(ctx context.Context) (bool, error) } @@ -15,6 +29,13 @@ type operations struct { apiClient APIClientInterface } +// Creates a point-in-time snapshot of a Typesense node's state and data in the specified directory. +// +// Creates a point-in-time snapshot of a Typesense node's state and data in the specified directory. You can then backup the snapshot directory that gets created and later restore it as a data directory, as needed. +// +// HTTP: POST /operations/snapshot +// +// See: https://typesense.org/docs/latest/api/cluster-operations.html func (o *operations) Snapshot(ctx context.Context, snapshotPath string) (bool, error) { response, err := o.apiClient.TakeSnapshotWithResponse(ctx, &api.TakeSnapshotParams{SnapshotPath: snapshotPath}) @@ -27,6 +48,13 @@ func (o *operations) Snapshot(ctx context.Context, snapshotPath string) (bool, e return response.JSON201.Success, nil } +// Triggers a follower node to initiate the raft voting process, which triggers leader re-election. +// +// Triggers a follower node to initiate the raft voting process, which triggers leader re-election. The follower node that you run this operation against will become the new leader, once this command succeeds. +// +// HTTP: POST /operations/vote +// +// See: https://typesense.org/docs/latest/api/cluster-operations.html func (o *operations) Vote(ctx context.Context) (bool, error) { response, err := o.apiClient.VoteWithResponse(ctx) if err != nil { diff --git a/typesense/preset.go b/typesense/preset.go index bae041a8..a2c5ed7f 100644 --- a/typesense/preset.go +++ b/typesense/preset.go @@ -7,7 +7,21 @@ import ( ) type PresetInterface interface { + // Retrieves a preset. + // + // Retrieve the details of a preset, given it's name. + // + // HTTP: GET /presets/{presetId} + // + // See: https://typesense.org/docs/latest/api/search.html#presets Retrieve(ctx context.Context) (*api.PresetSchema, error) + // Delete a preset. + // + // Permanently deletes a preset, given it's name. + // + // HTTP: DELETE /presets/{presetId} + // + // See: https://typesense.org/docs/latest/api/search.html#presets Delete(ctx context.Context) (*api.PresetDeleteSchema, error) } @@ -16,6 +30,13 @@ type preset struct { presetName string } +// Retrieves a preset. +// +// Retrieve the details of a preset, given it's name. +// +// HTTP: GET /presets/{presetId} +// +// See: https://typesense.org/docs/latest/api/search.html#presets func (p *preset) Retrieve(ctx context.Context) (*api.PresetSchema, error) { response, err := p.apiClient.RetrievePresetWithResponse(ctx, p.presetName) if err != nil { @@ -27,6 +48,13 @@ func (p *preset) Retrieve(ctx context.Context) (*api.PresetSchema, error) { return response.JSON200, nil } +// Delete a preset. +// +// Permanently deletes a preset, given it's name. +// +// HTTP: DELETE /presets/{presetId} +// +// See: https://typesense.org/docs/latest/api/search.html#presets func (p *preset) Delete(ctx context.Context) (*api.PresetDeleteSchema, error) { response, err := p.apiClient.DeletePresetWithResponse(ctx, p.presetName) if err != nil { diff --git a/typesense/presets.go b/typesense/presets.go index 16d17401..dbbed111 100644 --- a/typesense/presets.go +++ b/typesense/presets.go @@ -7,7 +7,21 @@ import ( ) type PresetsInterface interface { + // Retrieves all presets. + // + // Retrieve the details of all presets + // + // HTTP: GET /presets + // + // See: https://typesense.org/docs/latest/api/search.html#presets Retrieve(ctx context.Context) ([]*api.PresetSchema, error) + // Upserts a preset. + // + // Create or update an existing preset. + // + // HTTP: PUT /presets/{presetId} + // + // See: https://typesense.org/docs/latest/api/search.html#presets Upsert(ctx context.Context, presetName string, presetValue *api.PresetUpsertSchema) (*api.PresetSchema, error) } @@ -15,6 +29,13 @@ type presets struct { apiClient APIClientInterface } +// Retrieves all presets. +// +// # Retrieve the details of all presets +// +// HTTP: GET /presets +// +// See: https://typesense.org/docs/latest/api/search.html#presets func (p *presets) Retrieve(ctx context.Context) ([]*api.PresetSchema, error) { response, err := p.apiClient.RetrieveAllPresetsWithResponse(ctx) if err != nil { @@ -26,6 +47,13 @@ func (p *presets) Retrieve(ctx context.Context) ([]*api.PresetSchema, error) { return response.JSON200.Presets, nil } +// Upserts a preset. +// +// Create or update an existing preset. +// +// HTTP: PUT /presets/{presetId} +// +// See: https://typesense.org/docs/latest/api/search.html#presets func (p *presets) Upsert(ctx context.Context, presetName string, presetValue *api.PresetUpsertSchema) (*api.PresetSchema, error) { response, err := p.apiClient.UpsertPresetWithResponse(ctx, presetName, *presetValue) if err != nil { diff --git a/typesense/stats.go b/typesense/stats.go index 8274300a..32a467cc 100644 --- a/typesense/stats.go +++ b/typesense/stats.go @@ -7,6 +7,13 @@ import ( ) type StatsInterface interface { + // Get stats about API endpoints. + // + // Retrieve the stats about API endpoints. + // + // HTTP: GET /stats.json + // + // See: https://typesense.org/docs/latest/api/cluster-operations.html Retrieve(ctx context.Context) (*api.APIStatsResponse, error) } @@ -14,6 +21,13 @@ type stats struct { apiClient APIClientInterface } +// Get stats about API endpoints. +// +// Retrieve the stats about API endpoints. +// +// HTTP: GET /stats.json +// +// See: https://typesense.org/docs/latest/api/cluster-operations.html func (s *stats) Retrieve(ctx context.Context) (*api.APIStatsResponse, error) { response, err := s.apiClient.RetrieveAPIStatsWithResponse(ctx) if err != nil { diff --git a/typesense/stemming_dictionaries.go b/typesense/stemming_dictionaries.go index 31676ed2..6ccdf5ce 100644 --- a/typesense/stemming_dictionaries.go +++ b/typesense/stemming_dictionaries.go @@ -12,7 +12,21 @@ import ( type StemmingDictionariesInterface interface { Upsert(ctx context.Context, dictionaryId string, wordRootCombinations []api.StemmingDictionaryWord) ([]*api.StemmingDictionaryWord, error) + // Import a stemming dictionary. + // + // Upload a JSONL file containing word mappings to create or update a stemming dictionary. + // + // HTTP: POST /stemming/dictionaries/import + // + // See: https://typesense.org/docs/latest/api/stemming.html UpsertJsonl(ctx context.Context, dictionaryId string, body io.Reader) (io.ReadCloser, error) + // List all stemming dictionaries. + // + // Retrieve a list of all available stemming dictionaries. + // + // HTTP: GET /stemming/dictionaries + // + // See: https://typesense.org/docs/latest/api/stemming.html Retrieve(ctx context.Context) (*api.ListStemmingDictionariesResponse, error) } @@ -47,6 +61,13 @@ func (s *stemmingDictionaries) Upsert(ctx context.Context, dictionaryId string, return result, nil } +// Import a stemming dictionary. +// +// Upload a JSONL file containing word mappings to create or update a stemming dictionary. +// +// HTTP: POST /stemming/dictionaries/import +// +// See: https://typesense.org/docs/latest/api/stemming.html func (s *stemmingDictionaries) UpsertJsonl(ctx context.Context, dictionaryId string, body io.Reader) (io.ReadCloser, error) { params := &api.ImportStemmingDictionaryParams{ Id: dictionaryId, @@ -65,6 +86,13 @@ func (s *stemmingDictionaries) UpsertJsonl(ctx context.Context, dictionaryId str return response.Body, nil } +// List all stemming dictionaries. +// +// Retrieve a list of all available stemming dictionaries. +// +// HTTP: GET /stemming/dictionaries +// +// See: https://typesense.org/docs/latest/api/stemming.html func (s *stemmingDictionaries) Retrieve(ctx context.Context) (*api.ListStemmingDictionariesResponse, error) { response, err := s.apiClient.ListStemmingDictionariesWithResponse(ctx) if err != nil { diff --git a/typesense/stemming_dictionary.go b/typesense/stemming_dictionary.go index 2d471098..fdc35f44 100644 --- a/typesense/stemming_dictionary.go +++ b/typesense/stemming_dictionary.go @@ -7,6 +7,13 @@ import ( ) type StemmingDictionaryInterface interface { + // Retrieve a stemming dictionary. + // + // Fetch details of a specific stemming dictionary. + // + // HTTP: GET /stemming/dictionaries/{dictionaryId} + // + // See: https://typesense.org/docs/latest/api/stemming.html Retrieve(ctx context.Context) (*api.StemmingDictionary, error) } @@ -15,6 +22,13 @@ type stemmingDictionary struct { dictionaryId string } +// Retrieve a stemming dictionary. +// +// Fetch details of a specific stemming dictionary. +// +// HTTP: GET /stemming/dictionaries/{dictionaryId} +// +// See: https://typesense.org/docs/latest/api/stemming.html func (s *stemmingDictionary) Retrieve(ctx context.Context) (*api.StemmingDictionary, error) { response, err := s.apiClient.GetStemmingDictionaryWithResponse(ctx, s.dictionaryId) if err != nil { diff --git a/typesense/stopword.go b/typesense/stopword.go index 07c40a56..dee6dbe6 100644 --- a/typesense/stopword.go +++ b/typesense/stopword.go @@ -7,7 +7,21 @@ import ( ) type StopwordInterface interface { + // Retrieves a stopwords set. + // + // Retrieve the details of a stopwords set, given it's name. + // + // HTTP: GET /stopwords/{setId} + // + // See: https://typesense.org/docs/latest/api/stopwords.html Retrieve(ctx context.Context) (*api.StopwordsSetSchema, error) + // Delete a stopwords set. + // + // Permanently deletes a stopwords set, given it's name. + // + // HTTP: DELETE /stopwords/{setId} + // + // See: https://typesense.org/docs/latest/api/stopwords.html Delete(ctx context.Context) (*struct { Id string "json:\"id\"" }, error) @@ -18,6 +32,13 @@ type stopword struct { stopwordsSetId string } +// Retrieves a stopwords set. +// +// Retrieve the details of a stopwords set, given it's name. +// +// HTTP: GET /stopwords/{setId} +// +// See: https://typesense.org/docs/latest/api/stopwords.html func (s *stopword) Retrieve(ctx context.Context) (*api.StopwordsSetSchema, error) { response, err := s.apiClient.RetrieveStopwordsSetWithResponse(ctx, s.stopwordsSetId) if err != nil { @@ -29,6 +50,13 @@ func (s *stopword) Retrieve(ctx context.Context) (*api.StopwordsSetSchema, error return &response.JSON200.Stopwords, nil } +// Delete a stopwords set. +// +// Permanently deletes a stopwords set, given it's name. +// +// HTTP: DELETE /stopwords/{setId} +// +// See: https://typesense.org/docs/latest/api/stopwords.html func (s *stopword) Delete(ctx context.Context) (*struct { Id string "json:\"id\"" }, error) { diff --git a/typesense/stopwords.go b/typesense/stopwords.go index e8fdcdd8..ee32f9ec 100644 --- a/typesense/stopwords.go +++ b/typesense/stopwords.go @@ -7,7 +7,21 @@ import ( ) type StopwordsInterface interface { + // Retrieves all stopwords sets. + // + // Retrieve the details of all stopwords sets + // + // HTTP: GET /stopwords + // + // See: https://typesense.org/docs/latest/api/stopwords.html Retrieve(ctx context.Context) ([]api.StopwordsSetSchema, error) + // Upserts a stopwords set. + // + // When an analytics rule is created, we give it a name and describe the type, the source collections and the destination collection. + // + // HTTP: PUT /stopwords/{setId} + // + // See: https://typesense.org/docs/latest/api/stopwords.html Upsert(ctx context.Context, stopwordsSetId string, stopwordsSetUpsertSchema *api.StopwordsSetUpsertSchema) (*api.StopwordsSetSchema, error) } @@ -15,6 +29,13 @@ type stopwords struct { apiClient APIClientInterface } +// Retrieves all stopwords sets. +// +// # Retrieve the details of all stopwords sets +// +// HTTP: GET /stopwords +// +// See: https://typesense.org/docs/latest/api/stopwords.html func (s *stopwords) Retrieve(ctx context.Context) ([]api.StopwordsSetSchema, error) { response, err := s.apiClient.RetrieveStopwordsSetsWithResponse(ctx) if err != nil { @@ -26,6 +47,13 @@ func (s *stopwords) Retrieve(ctx context.Context) ([]api.StopwordsSetSchema, err return response.JSON200.Stopwords, nil } +// Upserts a stopwords set. +// +// When an analytics rule is created, we give it a name and describe the type, the source collections and the destination collection. +// +// HTTP: PUT /stopwords/{setId} +// +// See: https://typesense.org/docs/latest/api/stopwords.html func (s *stopwords) Upsert(ctx context.Context, stopwordsSetId string, stopwordsSetUpsertSchema *api.StopwordsSetUpsertSchema) (*api.StopwordsSetSchema, error) { response, err := s.apiClient.UpsertStopwordsSetWithResponse(ctx, stopwordsSetId, *stopwordsSetUpsertSchema) if err != nil { diff --git a/typesense/synonym_set.go b/typesense/synonym_set.go index 479f3726..747e3b88 100644 --- a/typesense/synonym_set.go +++ b/typesense/synonym_set.go @@ -8,11 +8,29 @@ import ( // SynonymSetInterface is a type for individual Synonym Set API operations type SynonymSetInterface interface { - // Retrieve a single synonym set + // Retrieve a synonym set. + // + // Retrieve a specific synonym set by its name + // + // HTTP: GET /synonym_sets/{synonymSetName} + // + // See: https://typesense.org/docs/latest/api/synonyms.html Retrieve(ctx context.Context) (*api.SynonymSetSchema, error) - // Update a synonym set + // Create or update a synonym set. + // + // Create or update a synonym set with the given name + // + // HTTP: PUT /synonym_sets/{synonymSetName} + // + // See: https://typesense.org/docs/latest/api/synonyms.html Upsert(ctx context.Context, synonymSetSchema *api.SynonymSetCreateSchema) (*api.SynonymSetSchema, error) - // Delete a synonym set + // Delete a synonym set. + // + // Delete a specific synonym set by its name + // + // HTTP: DELETE /synonym_sets/{synonymSetName} + // + // See: https://typesense.org/docs/latest/api/synonyms.html Delete(ctx context.Context) (*api.SynonymSetDeleteSchema, error) } @@ -22,6 +40,13 @@ type synonymSet struct { synonymSetName string } +// Retrieve a synonym set. +// +// # Retrieve a specific synonym set by its name +// +// HTTP: GET /synonym_sets/{synonymSetName} +// +// See: https://typesense.org/docs/latest/api/synonyms.html func (s *synonymSet) Retrieve(ctx context.Context) (*api.SynonymSetSchema, error) { response, err := s.apiClient.RetrieveSynonymSetWithResponse(ctx, s.synonymSetName) if err != nil { @@ -33,6 +58,13 @@ func (s *synonymSet) Retrieve(ctx context.Context) (*api.SynonymSetSchema, error return response.JSON200, nil } +// Create or update a synonym set. +// +// # Create or update a synonym set with the given name +// +// HTTP: PUT /synonym_sets/{synonymSetName} +// +// See: https://typesense.org/docs/latest/api/synonyms.html func (s *synonymSet) Upsert(ctx context.Context, synonymSetSchema *api.SynonymSetCreateSchema) (*api.SynonymSetSchema, error) { response, err := s.apiClient.UpsertSynonymSetWithResponse(ctx, s.synonymSetName, api.UpsertSynonymSetJSONRequestBody(*synonymSetSchema)) if err != nil { @@ -44,6 +76,13 @@ func (s *synonymSet) Upsert(ctx context.Context, synonymSetSchema *api.SynonymSe return response.JSON200, nil } +// Delete a synonym set. +// +// # Delete a specific synonym set by its name +// +// HTTP: DELETE /synonym_sets/{synonymSetName} +// +// See: https://typesense.org/docs/latest/api/synonyms.html func (s *synonymSet) Delete(ctx context.Context) (*api.SynonymSetDeleteSchema, error) { response, err := s.apiClient.DeleteSynonymSetWithResponse(ctx, s.synonymSetName) if err != nil { diff --git a/typesense/synonym_sets.go b/typesense/synonym_sets.go index 9a13db32..5bed870e 100644 --- a/typesense/synonym_sets.go +++ b/typesense/synonym_sets.go @@ -10,9 +10,21 @@ import ( // SynonymSetsInterface is a type for Synonym Sets API operations type SynonymSetsInterface interface { - // Create or update a synonym set + // Create or update a synonym set. + // + // Create or update a synonym set with the given name + // + // HTTP: PUT /synonym_sets/{synonymSetName} + // + // See: https://typesense.org/docs/latest/api/synonyms.html Upsert(ctx context.Context, synonymSetName string, synonymSetSchema *api.SynonymSetCreateSchema) (*api.SynonymSetSchema, error) + // List all synonym sets. + // // Retrieve all synonym sets + // + // HTTP: GET /synonym_sets + // + // See: https://typesense.org/docs/latest/api/synonyms.html Retrieve(ctx context.Context) ([]api.SynonymSetSchema, error) } @@ -21,6 +33,13 @@ type synonymSets struct { apiClient APIClientInterface } +// Create or update a synonym set. +// +// # Create or update a synonym set with the given name +// +// HTTP: PUT /synonym_sets/{synonymSetName} +// +// See: https://typesense.org/docs/latest/api/synonyms.html func (s *synonymSets) Upsert(ctx context.Context, synonymSetName string, synonymSetSchema *api.SynonymSetCreateSchema) (*api.SynonymSetSchema, error) { response, err := s.apiClient.UpsertSynonymSetWithResponse(ctx, synonymSetName, api.UpsertSynonymSetJSONRequestBody(*synonymSetSchema)) if err != nil { @@ -32,6 +51,13 @@ func (s *synonymSets) Upsert(ctx context.Context, synonymSetName string, synonym return response.JSON200, nil } +// List all synonym sets. +// +// # Retrieve all synonym sets +// +// HTTP: GET /synonym_sets +// +// See: https://typesense.org/docs/latest/api/synonyms.html func (s *synonymSets) Retrieve(ctx context.Context) ([]api.SynonymSetSchema, error) { response, err := s.apiClient.RetrieveSynonymSetsWithResponse(ctx) if err != nil {