@stainless-api/docs-search 0.1.0-beta.26 → 0.1.0-beta.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/context.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { f as ResultType, g as SearchSettings, h as SearchParams } from "./types-C_uoiqUJ.js";
1
+ import { ResultType, SearchParams, SearchSettings } from "./types.js";
2
2
  import * as react_jsx_runtime0 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/context.d.ts
package/dist/context.js CHANGED
@@ -1,5 +1,32 @@
1
- import "./indexer-CajKYSRj.js";
2
- import "./algolia-elwP_mmI.js";
3
- import { n as useSearch, r as useSearchContext, t as SearchProvider } from "./context-DIYY3XIj.js";
1
+ import { search } from "./providers/algolia.js";
2
+ import { createContext, useCallback, useContext } from "react";
3
+ import { jsx } from "react/jsx-runtime";
4
4
 
5
+ //#region src/context.tsx
6
+ function createStrictContext(displayName) {
7
+ const Context = createContext(null);
8
+ Context.displayName = displayName;
9
+ function useStrictContext() {
10
+ const context = useContext(Context);
11
+ if (context === null) throw new Error(`use${displayName} must be used within a ${displayName}Provider`);
12
+ return context;
13
+ }
14
+ return [Context.Provider, useStrictContext];
15
+ }
16
+ const [Provider, useSearchContext] = createStrictContext("SearchContext");
17
+ function useSearch() {
18
+ const { settings } = useSearchContext();
19
+ return useCallback((params) => search({
20
+ settings,
21
+ params
22
+ }), [settings]);
23
+ }
24
+ function SearchProvider({ children, ...props }) {
25
+ return /* @__PURE__ */ jsx(Provider, {
26
+ value: props,
27
+ children
28
+ });
29
+ }
30
+
31
+ //#endregion
5
32
  export { SearchProvider, useSearch, useSearchContext };
@@ -1,4 +1,3 @@
1
- import { DocsLanguage } from "@stainless-api/docs-ui/routing";
2
1
  import { Code } from "@pkg/plada/src/core";
3
2
 
4
3
  //#region ../sdk-json/index.d.ts
@@ -1510,91 +1509,4 @@ type GoTypePointer = BaseType & {
1510
1509
  inner: GoType;
1511
1510
  };
1512
1511
  //#endregion
1513
- //#region src/types.d.ts
1514
- type SearchSettings = {
1515
- appId: string;
1516
- searchKey: string;
1517
- indexName: string;
1518
- assistant?: string;
1519
- };
1520
- type SearchParams = {
1521
- query: string;
1522
- language?: DocsLanguage | null;
1523
- kind?: QueryKindsType | null;
1524
- };
1525
- declare const QueryKinds: readonly ["all", "guide", "resource", "http_method", "model", "property"];
1526
- type QueryKindsType = (typeof QueryKinds)[number];
1527
- type IndexModel = {
1528
- kind: 'model';
1529
- title: string;
1530
- children?: string[];
1531
- ident?: string;
1532
- };
1533
- type IndexProperty = {
1534
- kind: 'property';
1535
- docstring?: string;
1536
- type?: string;
1537
- };
1538
- type IndexResource = {
1539
- kind: 'resource';
1540
- title: string;
1541
- Name: string;
1542
- QualifiedName: string;
1543
- };
1544
- type IndexMethod = Pick<Method, 'kind' | 'summary' | 'description' | 'endpoint' | 'httpMethod'> & {
1545
- title: string;
1546
- qualified?: string;
1547
- ident?: string;
1548
- };
1549
- declare const SearchableAttributes: readonly ["name", "title", "ident", "Name", "qualified", "QualifiedName", "endpoint", "summary", "description", "docstring"];
1550
- declare const SearchableAttributesChat: string[];
1551
- declare const SearchableAttributesProse: string[];
1552
- type SearchAttributeNames = (typeof SearchableAttributes)[number];
1553
- type RoutableJsonNode = Method | Model | Resource;
1554
- type IndexEntry = Pick<RoutableJsonNode, 'name' | 'stainlessPath'> & (IndexProperty | IndexModel | IndexResource | IndexMethod) & {
1555
- language: DocsLanguage;
1556
- priority: number;
1557
- crumbs: string[];
1558
- };
1559
- type ResultRecordType = IndexEntry & {
1560
- objectID: string;
1561
- _highlightResult: Record<SearchAttributeNames, {
1562
- value: string;
1563
- }>;
1564
- };
1565
- type ResultType = {
1566
- hits: ResultRecordType[];
1567
- facets?: Record<string, Record<string, number>>;
1568
- nbHits: number;
1569
- };
1570
- type GuideResultType = {
1571
- id: string;
1572
- score: number;
1573
- words: number[];
1574
- data: {
1575
- excerpt: string;
1576
- url: string;
1577
- word_count: number;
1578
- meta: {
1579
- title: string;
1580
- };
1581
- sub_results: {
1582
- url: string;
1583
- title: string;
1584
- excerpt: string;
1585
- }[];
1586
- };
1587
- };
1588
- type ResultData = {
1589
- items: Array<ResultRecordType | GuideResultType>;
1590
- counts: Partial<Record<QueryKindsType, number>>;
1591
- };
1592
- type ProseIndexEntry = {
1593
- id?: string;
1594
- tag: string;
1595
- content: string;
1596
- source?: string;
1597
- [additional: string]: unknown;
1598
- };
1599
- //#endregion
1600
- export { SearchableAttributes as _, IndexProperty as a, Resource as b, QueryKinds as c, ResultRecordType as d, ResultType as f, SearchSettings as g, SearchParams as h, IndexModel as i, QueryKindsType as l, SearchAttributeNames as m, IndexEntry as n, IndexResource as o, RoutableJsonNode as p, IndexMethod as r, ProseIndexEntry as s, GuideResultType as t, ResultData as u, SearchableAttributesChat as v, Spec as x, SearchableAttributesProse as y };
1512
+ export { Spec as i, Model as n, Resource as r, Method as t };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { l as QueryKindsType, u as ResultData } from "./types-C_uoiqUJ.js";
1
+ import { QueryKindsType, ResultData } from "./types.js";
2
2
  import * as react_jsx_runtime0 from "react/jsx-runtime";
3
3
 
4
4
  //#region src/form.d.ts
package/dist/index.js CHANGED
@@ -1,8 +1,6 @@
1
- import "./indexer-CajKYSRj.js";
2
- import { t as QueryKinds } from "./types-DyGUPDP0.js";
3
- import "./algolia-elwP_mmI.js";
4
- import { n as useSearch, r as useSearchContext } from "./context-DIYY3XIj.js";
5
- import { t as guideSearch } from "./pagefind-DCvI8YmZ.js";
1
+ import { QueryKinds } from "./types.js";
2
+ import { useSearch, useSearchContext } from "./context.js";
3
+ import { guideSearch } from "./providers/pagefind.js";
6
4
  import { createElement, useEffect, useRef, useState } from "react";
7
5
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
8
6
  import { BookOpenText, Box, Code, Folder, Search, Wrench } from "lucide-react";
package/dist/indexer.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { b as Resource, n as IndexEntry, x as Spec } from "./types-C_uoiqUJ.js";
1
+ import { i as Spec, r as Resource } from "./index-ax9-8vsm.js";
2
+ import { IndexEntry } from "./types.js";
2
3
  import { DocsLanguage } from "@stainless-api/docs-ui/routing";
3
4
 
4
5
  //#region src/indexer.d.ts
@@ -17,7 +18,7 @@ declare function generateChatIndex(spec: Spec): Generator<{
17
18
  qualified?: undefined;
18
19
  ident?: undefined;
19
20
  } | {
20
- language: "node" | "cli" | "csharp" | "go" | "http" | "java" | "kotlin" | "php" | "python" | "ruby" | "terraform" | "typescript";
21
+ language: "cli" | "csharp" | "go" | "http" | "java" | "kotlin" | "node" | "php" | "python" | "ruby" | "terraform" | "typescript";
21
22
  title: string;
22
23
  name: string;
23
24
  endpoint: string;
package/dist/indexer.js CHANGED
@@ -1,3 +1,182 @@
1
- import { n as generateIndex, r as getResourceNames, t as generateChatIndex } from "./indexer-CajKYSRj.js";
1
+ import { Languages, generateRoute, parseStainlessPath, walkTree } from "@stainless-api/docs-ui/routing";
2
+ import { printer, renderMarkdown } from "@stainless-api/docs-ui/markdown";
2
3
 
4
+ //#region src/indexer.ts
5
+ function getResourceNames(resourceIds, topResources) {
6
+ let element = void 0;
7
+ let resources = topResources;
8
+ const resourceName = [];
9
+ for (const resource of resourceIds) {
10
+ element = resources?.[resource];
11
+ if (!element) break;
12
+ resourceName.push(element.title);
13
+ resources = element?.subresources;
14
+ }
15
+ return resourceName;
16
+ }
17
+ function chunkByLines(content, maxSize = 6e4) {
18
+ if (Buffer.byteLength(content, "utf8") < maxSize) return [content];
19
+ const lines = content.split("\n");
20
+ const chunks = [];
21
+ let currentChunk = [];
22
+ let currentSize = 0;
23
+ for (const line of lines) {
24
+ const lineSize = Buffer.byteLength(line + "\n", "utf8");
25
+ if (currentSize + lineSize > maxSize) {
26
+ chunks.push(currentChunk.join("\n"));
27
+ currentChunk = [];
28
+ currentSize = 0;
29
+ }
30
+ currentChunk.push(line);
31
+ currentSize += lineSize;
32
+ }
33
+ if (currentChunk.length > 0) chunks.push(currentChunk.join("\n"));
34
+ return chunks;
35
+ }
36
+ function* generateChatIndex(spec) {
37
+ for (const [language, readme] of Object.entries(spec.readme)) {
38
+ const chunks = chunkByLines(readme);
39
+ for (const chunk of chunks) yield {
40
+ language,
41
+ title: "Overview",
42
+ content: chunk,
43
+ url: `docs://BASE_PATH/${language}`
44
+ };
45
+ }
46
+ for (const { data } of walkTree(spec)) {
47
+ if (data.kind !== "http_method") continue;
48
+ const { title, name, stainlessPath, httpMethod, summary, description } = data;
49
+ const endpoint = data.endpoint.slice(httpMethod.length).trim();
50
+ for (const language of Languages) {
51
+ const decl = spec.decls[language]?.[stainlessPath];
52
+ if (!decl) continue;
53
+ const chunks = chunkByLines(renderMarkdown({
54
+ spec,
55
+ language,
56
+ options: { includeModelProperties: true }
57
+ }, data));
58
+ for (const chunk of chunks) yield {
59
+ language,
60
+ title,
61
+ name,
62
+ endpoint,
63
+ httpMethod,
64
+ summary,
65
+ description,
66
+ stainlessPath,
67
+ qualified: "qualified" in decl ? decl["qualified"] : void 0,
68
+ ident: "ident" in decl ? decl["ident"] : void 0,
69
+ content: chunk,
70
+ url: generateRoute("docs://BASE_PATH", language, stainlessPath)
71
+ };
72
+ }
73
+ }
74
+ }
75
+ function* generateIndex(spec, renderMarkdownFn, includeTypes, languages) {
76
+ const parentCrumbs = {};
77
+ const targetLangs = languages ?? Languages;
78
+ for (const { data } of walkTree(spec, true)) {
79
+ const { kind, name, title, stainlessPath } = data;
80
+ const common = {
81
+ name,
82
+ title,
83
+ stainlessPath
84
+ };
85
+ const crumbs = getResourceNames(parseStainlessPath(stainlessPath).resource, spec.resources);
86
+ switch (kind) {
87
+ case "resource":
88
+ for (const language of targetLangs) {
89
+ if (!data[language]) continue;
90
+ parentCrumbs[stainlessPath] = crumbs;
91
+ const { Name, QualifiedName } = data[language];
92
+ yield {
93
+ kind,
94
+ crumbs,
95
+ language,
96
+ Name,
97
+ QualifiedName,
98
+ priority: 0,
99
+ ...common
100
+ };
101
+ }
102
+ break;
103
+ case "http_method": {
104
+ const { summary, endpoint, httpMethod } = data;
105
+ for (const language of targetLangs) {
106
+ const found = spec.decls[language]?.[stainlessPath];
107
+ if (!found) continue;
108
+ parentCrumbs[stainlessPath] = [...crumbs, title];
109
+ const qualified = "qualified" in found ? found["qualified"] : void 0;
110
+ const ident = qualified?.split(".")?.at(-1);
111
+ yield {
112
+ kind,
113
+ crumbs: [...crumbs, title],
114
+ ident,
115
+ qualified,
116
+ language,
117
+ description: data.description ? renderMarkdownFn?.(data.description) ?? data.description : void 0,
118
+ endpoint: endpoint.slice(httpMethod.length).trim(),
119
+ httpMethod,
120
+ summary,
121
+ priority: 0,
122
+ ...common
123
+ };
124
+ }
125
+ break;
126
+ }
127
+ case "model": for (const language of targetLangs) {
128
+ if (!spec.decls[language]) continue;
129
+ parentCrumbs[stainlessPath] = [...crumbs, title];
130
+ const schema = spec.decls[language]?.[`${stainlessPath} > (schema)`];
131
+ const children = (schema && "children" in schema ? schema?.["children"] : void 0)?.map((childPath) => {
132
+ const child = spec.decls?.[language]?.[childPath];
133
+ return child?.["ident"] ?? child?.["name"] ?? child?.["key"] ?? child?.["type"]?.["literal"]?.["value"] ?? child?.["type"]?.["literal"] ?? child?.["type"]?.["value"];
134
+ })?.filter((child) => child) ?? [];
135
+ yield {
136
+ kind,
137
+ crumbs: [...crumbs, title],
138
+ children,
139
+ language,
140
+ priority: 2,
141
+ ident: schema && "ident" in schema ? schema?.["ident"] : void 0,
142
+ ...common
143
+ };
144
+ }
145
+ }
146
+ }
147
+ for (const language of targetLangs) {
148
+ const decls = spec.decls?.[language];
149
+ if (!decls) continue;
150
+ for (const decl of Object.values(decls)) switch (decl.kind) {
151
+ case "JavaDeclProperty":
152
+ case "GoDeclProperty":
153
+ case "PythonDeclProperty":
154
+ case "RubyDeclProperty":
155
+ case "HttpDeclProperty":
156
+ case "TSDeclProperty":
157
+ {
158
+ const parsedPath = parseStainlessPath(decl.stainlessPath);
159
+ const type = includeTypes === false ? void 0 : printer.typeName(language, decl.type);
160
+ const name = decl["ident"] ?? decl["name"] ?? decl["key"];
161
+ const parent = parentCrumbs[parsedPath.routable];
162
+ if (parent === void 0) continue;
163
+ const matches = decl.stainlessPath.matchAll(/\((property|params|param)\) ([^\s]+)/g);
164
+ const props = Array.from(matches).map((p) => p[2]).filter((p) => p !== void 0);
165
+ yield {
166
+ kind: "property",
167
+ name,
168
+ stainlessPath: decl.stainlessPath,
169
+ crumbs: [...parent, ...props],
170
+ docstring: decl.docstring ? renderMarkdownFn?.(decl.docstring) ?? decl.docstring : void 0,
171
+ type,
172
+ language,
173
+ priority: 3
174
+ };
175
+ }
176
+ break;
177
+ }
178
+ }
179
+ }
180
+
181
+ //#endregion
3
182
  export { generateChatIndex, generateIndex, getResourceNames };
package/dist/mcp.d.ts CHANGED
@@ -1,4 +1,5 @@
1
- import { n as IndexEntry, r as IndexMethod, x as Spec } from "./types-C_uoiqUJ.js";
1
+ import { i as Spec } from "./index-ax9-8vsm.js";
2
+ import { IndexEntry, IndexMethod } from "./types.js";
2
3
  import { generateIndex } from "./indexer.js";
3
4
  import { DocsLanguage } from "@stainless-api/docs-ui/routing";
4
5
 
package/dist/mcp.js CHANGED
@@ -1,4 +1,4 @@
1
- import { n as generateIndex } from "./indexer-CajKYSRj.js";
1
+ import { generateIndex } from "./indexer.js";
2
2
  import { parseStainlessPath } from "@stainless-api/docs-ui/routing";
3
3
  import { renderMarkdown } from "@stainless-api/docs-ui/markdown";
4
4
  import { getResourceFromSpec } from "@stainless-api/docs-ui/utils";
@@ -1,4 +1,5 @@
1
- import { f as ResultType, g as SearchSettings, h as SearchParams, n as IndexEntry, s as ProseIndexEntry, x as Spec } from "../types-C_uoiqUJ.js";
1
+ import { i as Spec } from "../index-ax9-8vsm.js";
2
+ import { IndexEntry, ProseIndexEntry, ResultType, SearchParams, SearchSettings } from "../types.js";
2
3
 
3
4
  //#region src/providers/algolia.d.ts
4
5
  declare function buildIndex(appId: string, indexName: string, writeKey: string, content: Spec | IndexEntry[], renderMarkdown: (_: string) => string | null): Promise<void>;
@@ -1,4 +1,83 @@
1
- import "../indexer-CajKYSRj.js";
2
- import { i as search, n as buildIndex, r as buildProseIndex, t as buildChatIndex } from "../algolia-elwP_mmI.js";
1
+ import { generateChatIndex, generateIndex } from "../indexer.js";
2
+ import { SearchableAttributes, SearchableAttributesChat, SearchableAttributesProse } from "../types.js";
3
+ import { searchClient } from "@algolia/client-search";
3
4
 
5
+ //#region src/providers/algolia.ts
6
+ async function buildIndex(appId, indexName, writeKey, content, renderMarkdown) {
7
+ if (!appId || !indexName || !writeKey) return;
8
+ const objects = Array.isArray(content) ? content : Array.from(generateIndex(content, renderMarkdown));
9
+ const client = searchClient(appId, writeKey);
10
+ await client.setSettings({
11
+ indexName,
12
+ indexSettings: {
13
+ highlightPreTag: "<mark>",
14
+ highlightPostTag: "</mark>",
15
+ customRanking: ["asc(priority)"],
16
+ attributesForFaceting: ["language", "kind"],
17
+ searchableAttributes: [...SearchableAttributes]
18
+ }
19
+ });
20
+ await client.replaceAllObjects({
21
+ indexName,
22
+ objects
23
+ });
24
+ }
25
+ async function buildChatIndex(appId, indexName, writeKey, spec) {
26
+ if (!appId || !indexName || !writeKey) return;
27
+ const objects = Array.from(generateChatIndex(spec));
28
+ const client = searchClient(appId, writeKey);
29
+ await client.setSettings({
30
+ indexName,
31
+ indexSettings: {
32
+ attributesForFaceting: ["language"],
33
+ attributeForDistinct: "stainlessPath",
34
+ searchableAttributes: SearchableAttributesChat
35
+ }
36
+ });
37
+ await client.replaceAllObjects({
38
+ indexName,
39
+ objects
40
+ });
41
+ }
42
+ async function buildProseIndex(appId, indexName, writeKey, objects) {
43
+ if (!appId || !indexName || !writeKey) return;
44
+ const client = searchClient(appId, writeKey);
45
+ await client.setSettings({
46
+ indexName,
47
+ indexSettings: { searchableAttributes: SearchableAttributesProse }
48
+ });
49
+ await client.replaceAllObjects({
50
+ indexName,
51
+ objects
52
+ });
53
+ }
54
+ async function search({ settings: { appId, indexName, searchKey }, params: { query, language, kind } }) {
55
+ const client = searchClient(appId, searchKey);
56
+ const filters = language ? `language:${language}` : void 0;
57
+ const facetFilters = kind ? [`kind:${kind}`] : void 0;
58
+ const { results } = await client.search({ requests: [{
59
+ query,
60
+ indexName,
61
+ filters,
62
+ hitsPerPage: 5,
63
+ facets: ["kind"]
64
+ }, {
65
+ query,
66
+ indexName,
67
+ filters,
68
+ facetFilters,
69
+ facets: ["kind"],
70
+ hitsPerPage: 50
71
+ }] });
72
+ if ("hits" in results[0] && "hits" in results[1]) {
73
+ const [{ nbHits, facets }, { hits }] = results;
74
+ return {
75
+ hits,
76
+ nbHits: nbHits ?? 0,
77
+ facets
78
+ };
79
+ }
80
+ }
81
+
82
+ //#endregion
4
83
  export { buildChatIndex, buildIndex, buildProseIndex, search };
@@ -1,4 +1,5 @@
1
- import { n as IndexEntry, x as Spec } from "../types-C_uoiqUJ.js";
1
+ import { i as Spec } from "../index-ax9-8vsm.js";
2
+ import { IndexEntry } from "../types.js";
2
3
  import { DocsLanguage } from "@stainless-api/docs-ui/routing";
3
4
  import * as fuse_js0 from "fuse.js";
4
5
  import { FuseIndex } from "fuse.js";
@@ -1,5 +1,5 @@
1
- import { n as generateIndex } from "../indexer-CajKYSRj.js";
2
- import { n as SearchableAttributes } from "../types-DyGUPDP0.js";
1
+ import { generateIndex } from "../indexer.js";
2
+ import { SearchableAttributes } from "../types.js";
3
3
  import Fuse from "fuse.js";
4
4
 
5
5
  //#region src/providers/fuse.ts
@@ -1,4 +1,4 @@
1
- import { t as GuideResultType } from "../types-C_uoiqUJ.js";
1
+ import { GuideResultType } from "../types.js";
2
2
 
3
3
  //#region src/providers/pagefind.d.ts
4
4
  declare function guideSearch(loadPath: string, query: string, limit?: number): Promise<GuideResultType[]>;
@@ -1,3 +1,15 @@
1
- import { t as guideSearch } from "../pagefind-DCvI8YmZ.js";
1
+ //#region src/providers/pagefind.ts
2
+ async function loadPagefind(path) {
3
+ return await import(new URL(path, import.meta.url).href);
4
+ }
5
+ async function guideSearch(loadPath, query, limit) {
6
+ const response = await (await loadPagefind(loadPath)).search(query);
7
+ const items = limit ? response.results.slice(0, limit) : response.results;
8
+ return Promise.all(items.map((result) => result.data().then((data) => ({
9
+ ...result,
10
+ data
11
+ }))));
12
+ }
2
13
 
14
+ //#endregion
3
15
  export { guideSearch };
@@ -1,4 +1,5 @@
1
- import { n as IndexEntry, x as Spec } from "../types-C_uoiqUJ.js";
1
+ import { i as Spec } from "../index-ax9-8vsm.js";
2
+ import { IndexEntry } from "../types.js";
2
3
  import { DocsLanguage } from "@stainless-api/docs-ui/routing";
3
4
 
4
5
  //#region src/providers/walker.d.ts
@@ -1,5 +1,5 @@
1
- import { n as generateIndex } from "../indexer-CajKYSRj.js";
2
- import { n as SearchableAttributes } from "../types-DyGUPDP0.js";
1
+ import { generateIndex } from "../indexer.js";
2
+ import { SearchableAttributes } from "../types.js";
3
3
 
4
4
  //#region src/providers/walker.ts
5
5
  function buildIndex(spec) {
package/dist/types.d.ts CHANGED
@@ -1,2 +1,91 @@
1
- import { _ as SearchableAttributes, a as IndexProperty, c as QueryKinds, d as ResultRecordType, f as ResultType, g as SearchSettings, h as SearchParams, i as IndexModel, l as QueryKindsType, m as SearchAttributeNames, n as IndexEntry, o as IndexResource, p as RoutableJsonNode, r as IndexMethod, s as ProseIndexEntry, t as GuideResultType, u as ResultData, v as SearchableAttributesChat, y as SearchableAttributesProse } from "./types-C_uoiqUJ.js";
1
+ import { n as Model, r as Resource, t as Method } from "./index-ax9-8vsm.js";
2
+ import { DocsLanguage } from "@stainless-api/docs-ui/routing";
3
+
4
+ //#region src/types.d.ts
5
+ type SearchSettings = {
6
+ appId: string;
7
+ searchKey: string;
8
+ indexName: string;
9
+ assistant?: string;
10
+ };
11
+ type SearchParams = {
12
+ query: string;
13
+ language?: DocsLanguage | null;
14
+ kind?: QueryKindsType | null;
15
+ };
16
+ declare const QueryKinds: readonly ["all", "guide", "resource", "http_method", "model", "property"];
17
+ type QueryKindsType = (typeof QueryKinds)[number];
18
+ type IndexModel = {
19
+ kind: 'model';
20
+ title: string;
21
+ children?: string[];
22
+ ident?: string;
23
+ };
24
+ type IndexProperty = {
25
+ kind: 'property';
26
+ docstring?: string;
27
+ type?: string;
28
+ };
29
+ type IndexResource = {
30
+ kind: 'resource';
31
+ title: string;
32
+ Name: string;
33
+ QualifiedName: string;
34
+ };
35
+ type IndexMethod = Pick<Method, 'kind' | 'summary' | 'description' | 'endpoint' | 'httpMethod'> & {
36
+ title: string;
37
+ qualified?: string;
38
+ ident?: string;
39
+ };
40
+ declare const SearchableAttributes: readonly ["name", "title", "ident", "Name", "qualified", "QualifiedName", "endpoint", "summary", "description", "docstring"];
41
+ declare const SearchableAttributesChat: string[];
42
+ declare const SearchableAttributesProse: string[];
43
+ type SearchAttributeNames = (typeof SearchableAttributes)[number];
44
+ type RoutableJsonNode = Method | Model | Resource;
45
+ type IndexEntry = Pick<RoutableJsonNode, 'name' | 'stainlessPath'> & (IndexProperty | IndexModel | IndexResource | IndexMethod) & {
46
+ language: DocsLanguage;
47
+ priority: number;
48
+ crumbs: string[];
49
+ };
50
+ type ResultRecordType = IndexEntry & {
51
+ objectID: string;
52
+ _highlightResult: Record<SearchAttributeNames, {
53
+ value: string;
54
+ }>;
55
+ };
56
+ type ResultType = {
57
+ hits: ResultRecordType[];
58
+ facets?: Record<string, Record<string, number>>;
59
+ nbHits: number;
60
+ };
61
+ type GuideResultType = {
62
+ id: string;
63
+ score: number;
64
+ words: number[];
65
+ data: {
66
+ excerpt: string;
67
+ url: string;
68
+ word_count: number;
69
+ meta: {
70
+ title: string;
71
+ };
72
+ sub_results: {
73
+ url: string;
74
+ title: string;
75
+ excerpt: string;
76
+ }[];
77
+ };
78
+ };
79
+ type ResultData = {
80
+ items: Array<ResultRecordType | GuideResultType>;
81
+ counts: Partial<Record<QueryKindsType, number>>;
82
+ };
83
+ type ProseIndexEntry = {
84
+ id?: string;
85
+ tag: string;
86
+ content: string;
87
+ source?: string;
88
+ [additional: string]: unknown;
89
+ };
90
+ //#endregion
2
91
  export { GuideResultType, IndexEntry, IndexMethod, IndexModel, IndexProperty, IndexResource, ProseIndexEntry, QueryKinds, QueryKindsType, ResultData, ResultRecordType, ResultType, RoutableJsonNode, SearchAttributeNames, SearchParams, SearchSettings, SearchableAttributes, SearchableAttributesChat, SearchableAttributesProse };
package/dist/types.js CHANGED
@@ -1,3 +1,35 @@
1
- import { i as SearchableAttributesProse, n as SearchableAttributes, r as SearchableAttributesChat, t as QueryKinds } from "./types-DyGUPDP0.js";
1
+ //#region src/types.ts
2
+ const QueryKinds = [
3
+ "all",
4
+ "guide",
5
+ "resource",
6
+ "http_method",
7
+ "model",
8
+ "property"
9
+ ];
10
+ const SearchableAttributes = [
11
+ "name",
12
+ "title",
13
+ "ident",
14
+ "Name",
15
+ "qualified",
16
+ "QualifiedName",
17
+ "endpoint",
18
+ "summary",
19
+ "description",
20
+ "docstring"
21
+ ];
22
+ const SearchableAttributesChat = [
23
+ "title",
24
+ "name",
25
+ "endpoint",
26
+ "summary",
27
+ "description",
28
+ "qualified",
29
+ "ident",
30
+ "content"
31
+ ];
32
+ const SearchableAttributesProse = ["content"];
2
33
 
34
+ //#endregion
3
35
  export { QueryKinds, SearchableAttributes, SearchableAttributesChat, SearchableAttributesProse };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stainless-api/docs-search",
3
- "version": "0.1.0-beta.26",
3
+ "version": "0.1.0-beta.27",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -19,7 +19,7 @@
19
19
  "fuse.js": "^7.1.0",
20
20
  "htmlparser2": "^10.1.0",
21
21
  "lucide-react": "^0.562.0",
22
- "@stainless-api/docs-ui": "0.1.0-beta.73",
22
+ "@stainless-api/docs-ui": "0.1.0-beta.74",
23
23
  "@stainless-api/ui-primitives": "0.1.0-beta.47"
24
24
  },
25
25
  "devDependencies": {
@@ -29,7 +29,7 @@
29
29
  "dotenv": "17.2.3",
30
30
  "react": "^19.2.4",
31
31
  "react-dom": "^19.2.4",
32
- "tsdown": "^0.20.0",
32
+ "tsdown": "^0.20.3",
33
33
  "typescript": "5.9.3",
34
34
  "@stainless/eslint-config": "0.1.0-beta.1",
35
35
  "@stainless/sdk-json": "^0.1.0-beta.6"
@@ -1,83 +0,0 @@
1
- import { n as generateIndex, t as generateChatIndex } from "./indexer-CajKYSRj.js";
2
- import { i as SearchableAttributesProse, n as SearchableAttributes, r as SearchableAttributesChat } from "./types-DyGUPDP0.js";
3
- import { searchClient } from "@algolia/client-search";
4
-
5
- //#region src/providers/algolia.ts
6
- async function buildIndex(appId, indexName, writeKey, content, renderMarkdown) {
7
- if (!appId || !indexName || !writeKey) return;
8
- const objects = Array.isArray(content) ? content : Array.from(generateIndex(content, renderMarkdown));
9
- const client = searchClient(appId, writeKey);
10
- await client.setSettings({
11
- indexName,
12
- indexSettings: {
13
- highlightPreTag: "<mark>",
14
- highlightPostTag: "</mark>",
15
- customRanking: ["asc(priority)"],
16
- attributesForFaceting: ["language", "kind"],
17
- searchableAttributes: [...SearchableAttributes]
18
- }
19
- });
20
- await client.replaceAllObjects({
21
- indexName,
22
- objects
23
- });
24
- }
25
- async function buildChatIndex(appId, indexName, writeKey, spec) {
26
- if (!appId || !indexName || !writeKey) return;
27
- const objects = Array.from(generateChatIndex(spec));
28
- const client = searchClient(appId, writeKey);
29
- await client.setSettings({
30
- indexName,
31
- indexSettings: {
32
- attributesForFaceting: ["language"],
33
- attributeForDistinct: "stainlessPath",
34
- searchableAttributes: SearchableAttributesChat
35
- }
36
- });
37
- await client.replaceAllObjects({
38
- indexName,
39
- objects
40
- });
41
- }
42
- async function buildProseIndex(appId, indexName, writeKey, objects) {
43
- if (!appId || !indexName || !writeKey) return;
44
- const client = searchClient(appId, writeKey);
45
- await client.setSettings({
46
- indexName,
47
- indexSettings: { searchableAttributes: SearchableAttributesProse }
48
- });
49
- await client.replaceAllObjects({
50
- indexName,
51
- objects
52
- });
53
- }
54
- async function search({ settings: { appId, indexName, searchKey }, params: { query, language, kind } }) {
55
- const client = searchClient(appId, searchKey);
56
- const filters = language ? `language:${language}` : void 0;
57
- const facetFilters = kind ? [`kind:${kind}`] : void 0;
58
- const { results } = await client.search({ requests: [{
59
- query,
60
- indexName,
61
- filters,
62
- hitsPerPage: 5,
63
- facets: ["kind"]
64
- }, {
65
- query,
66
- indexName,
67
- filters,
68
- facetFilters,
69
- facets: ["kind"],
70
- hitsPerPage: 50
71
- }] });
72
- if ("hits" in results[0] && "hits" in results[1]) {
73
- const [{ nbHits, facets }, { hits }] = results;
74
- return {
75
- hits,
76
- nbHits: nbHits ?? 0,
77
- facets
78
- };
79
- }
80
- }
81
-
82
- //#endregion
83
- export { search as i, buildIndex as n, buildProseIndex as r, buildChatIndex as t };
@@ -1,32 +0,0 @@
1
- import { i as search } from "./algolia-elwP_mmI.js";
2
- import { createContext, useCallback, useContext } from "react";
3
- import { jsx } from "react/jsx-runtime";
4
-
5
- //#region src/context.tsx
6
- function createStrictContext(displayName) {
7
- const Context = createContext(null);
8
- Context.displayName = displayName;
9
- function useStrictContext() {
10
- const context = useContext(Context);
11
- if (context === null) throw new Error(`use${displayName} must be used within a ${displayName}Provider`);
12
- return context;
13
- }
14
- return [Context.Provider, useStrictContext];
15
- }
16
- const [Provider, useSearchContext] = createStrictContext("SearchContext");
17
- function useSearch() {
18
- const { settings } = useSearchContext();
19
- return useCallback((params) => search({
20
- settings,
21
- params
22
- }), [settings]);
23
- }
24
- function SearchProvider({ children, ...props }) {
25
- return /* @__PURE__ */ jsx(Provider, {
26
- value: props,
27
- children
28
- });
29
- }
30
-
31
- //#endregion
32
- export { useSearch as n, useSearchContext as r, SearchProvider as t };
@@ -1,182 +0,0 @@
1
- import { Languages, generateRoute, parseStainlessPath, walkTree } from "@stainless-api/docs-ui/routing";
2
- import { printer, renderMarkdown } from "@stainless-api/docs-ui/markdown";
3
-
4
- //#region src/indexer.ts
5
- function getResourceNames(resourceIds, topResources) {
6
- let element = void 0;
7
- let resources = topResources;
8
- const resourceName = [];
9
- for (const resource of resourceIds) {
10
- element = resources?.[resource];
11
- if (!element) break;
12
- resourceName.push(element.title);
13
- resources = element?.subresources;
14
- }
15
- return resourceName;
16
- }
17
- function chunkByLines(content, maxSize = 6e4) {
18
- if (Buffer.byteLength(content, "utf8") < maxSize) return [content];
19
- const lines = content.split("\n");
20
- const chunks = [];
21
- let currentChunk = [];
22
- let currentSize = 0;
23
- for (const line of lines) {
24
- const lineSize = Buffer.byteLength(line + "\n", "utf8");
25
- if (currentSize + lineSize > maxSize) {
26
- chunks.push(currentChunk.join("\n"));
27
- currentChunk = [];
28
- currentSize = 0;
29
- }
30
- currentChunk.push(line);
31
- currentSize += lineSize;
32
- }
33
- if (currentChunk.length > 0) chunks.push(currentChunk.join("\n"));
34
- return chunks;
35
- }
36
- function* generateChatIndex(spec) {
37
- for (const [language, readme] of Object.entries(spec.readme)) {
38
- const chunks = chunkByLines(readme);
39
- for (const chunk of chunks) yield {
40
- language,
41
- title: "Overview",
42
- content: chunk,
43
- url: `docs://BASE_PATH/${language}`
44
- };
45
- }
46
- for (const { data } of walkTree(spec)) {
47
- if (data.kind !== "http_method") continue;
48
- const { title, name, stainlessPath, httpMethod, summary, description } = data;
49
- const endpoint = data.endpoint.slice(httpMethod.length).trim();
50
- for (const language of Languages) {
51
- const decl = spec.decls[language]?.[stainlessPath];
52
- if (!decl) continue;
53
- const chunks = chunkByLines(renderMarkdown({
54
- spec,
55
- language,
56
- options: { includeModelProperties: true }
57
- }, data));
58
- for (const chunk of chunks) yield {
59
- language,
60
- title,
61
- name,
62
- endpoint,
63
- httpMethod,
64
- summary,
65
- description,
66
- stainlessPath,
67
- qualified: "qualified" in decl ? decl["qualified"] : void 0,
68
- ident: "ident" in decl ? decl["ident"] : void 0,
69
- content: chunk,
70
- url: generateRoute("docs://BASE_PATH", language, stainlessPath)
71
- };
72
- }
73
- }
74
- }
75
- function* generateIndex(spec, renderMarkdownFn, includeTypes, languages) {
76
- const parentCrumbs = {};
77
- const targetLangs = languages ?? Languages;
78
- for (const { data } of walkTree(spec, true)) {
79
- const { kind, name, title, stainlessPath } = data;
80
- const common = {
81
- name,
82
- title,
83
- stainlessPath
84
- };
85
- const crumbs = getResourceNames(parseStainlessPath(stainlessPath).resource, spec.resources);
86
- switch (kind) {
87
- case "resource":
88
- for (const language of targetLangs) {
89
- if (!data[language]) continue;
90
- parentCrumbs[stainlessPath] = crumbs;
91
- const { Name, QualifiedName } = data[language];
92
- yield {
93
- kind,
94
- crumbs,
95
- language,
96
- Name,
97
- QualifiedName,
98
- priority: 0,
99
- ...common
100
- };
101
- }
102
- break;
103
- case "http_method": {
104
- const { summary, endpoint, httpMethod } = data;
105
- for (const language of targetLangs) {
106
- const found = spec.decls[language]?.[stainlessPath];
107
- if (!found) continue;
108
- parentCrumbs[stainlessPath] = [...crumbs, title];
109
- const qualified = "qualified" in found ? found["qualified"] : void 0;
110
- const ident = qualified?.split(".")?.at(-1);
111
- yield {
112
- kind,
113
- crumbs: [...crumbs, title],
114
- ident,
115
- qualified,
116
- language,
117
- description: data.description ? renderMarkdownFn?.(data.description) ?? data.description : void 0,
118
- endpoint: endpoint.slice(httpMethod.length).trim(),
119
- httpMethod,
120
- summary,
121
- priority: 0,
122
- ...common
123
- };
124
- }
125
- break;
126
- }
127
- case "model": for (const language of targetLangs) {
128
- if (!spec.decls[language]) continue;
129
- parentCrumbs[stainlessPath] = [...crumbs, title];
130
- const schema = spec.decls[language]?.[`${stainlessPath} > (schema)`];
131
- const children = (schema && "children" in schema ? schema?.["children"] : void 0)?.map((childPath) => {
132
- const child = spec.decls?.[language]?.[childPath];
133
- return child?.["ident"] ?? child?.["name"] ?? child?.["key"] ?? child?.["type"]?.["literal"]?.["value"] ?? child?.["type"]?.["literal"] ?? child?.["type"]?.["value"];
134
- })?.filter((child) => child) ?? [];
135
- yield {
136
- kind,
137
- crumbs: [...crumbs, title],
138
- children,
139
- language,
140
- priority: 2,
141
- ident: schema && "ident" in schema ? schema?.["ident"] : void 0,
142
- ...common
143
- };
144
- }
145
- }
146
- }
147
- for (const language of targetLangs) {
148
- const decls = spec.decls?.[language];
149
- if (!decls) continue;
150
- for (const decl of Object.values(decls)) switch (decl.kind) {
151
- case "JavaDeclProperty":
152
- case "GoDeclProperty":
153
- case "PythonDeclProperty":
154
- case "RubyDeclProperty":
155
- case "HttpDeclProperty":
156
- case "TSDeclProperty":
157
- {
158
- const parsedPath = parseStainlessPath(decl.stainlessPath);
159
- const type = includeTypes === false ? void 0 : printer.typeName(language, decl.type);
160
- const name = decl["ident"] ?? decl["name"] ?? decl["key"];
161
- const parent = parentCrumbs[parsedPath.routable];
162
- if (parent === void 0) continue;
163
- const matches = decl.stainlessPath.matchAll(/\((property|params|param)\) ([^\s]+)/g);
164
- const props = Array.from(matches).map((p) => p[2]).filter((p) => p !== void 0);
165
- yield {
166
- kind: "property",
167
- name,
168
- stainlessPath: decl.stainlessPath,
169
- crumbs: [...parent, ...props],
170
- docstring: decl.docstring ? renderMarkdownFn?.(decl.docstring) ?? decl.docstring : void 0,
171
- type,
172
- language,
173
- priority: 3
174
- };
175
- }
176
- break;
177
- }
178
- }
179
- }
180
-
181
- //#endregion
182
- export { generateIndex as n, getResourceNames as r, generateChatIndex as t };
@@ -1,15 +0,0 @@
1
- //#region src/providers/pagefind.ts
2
- async function loadPagefind(path) {
3
- return await import(new URL(path, import.meta.url).href);
4
- }
5
- async function guideSearch(loadPath, query, limit) {
6
- const response = await (await loadPagefind(loadPath)).search(query);
7
- const items = limit ? response.results.slice(0, limit) : response.results;
8
- return Promise.all(items.map((result) => result.data().then((data) => ({
9
- ...result,
10
- data
11
- }))));
12
- }
13
-
14
- //#endregion
15
- export { guideSearch as t };
@@ -1,35 +0,0 @@
1
- //#region src/types.ts
2
- const QueryKinds = [
3
- "all",
4
- "guide",
5
- "resource",
6
- "http_method",
7
- "model",
8
- "property"
9
- ];
10
- const SearchableAttributes = [
11
- "name",
12
- "title",
13
- "ident",
14
- "Name",
15
- "qualified",
16
- "QualifiedName",
17
- "endpoint",
18
- "summary",
19
- "description",
20
- "docstring"
21
- ];
22
- const SearchableAttributesChat = [
23
- "title",
24
- "name",
25
- "endpoint",
26
- "summary",
27
- "description",
28
- "qualified",
29
- "ident",
30
- "content"
31
- ];
32
- const SearchableAttributesProse = ["content"];
33
-
34
- //#endregion
35
- export { SearchableAttributesProse as i, SearchableAttributes as n, SearchableAttributesChat as r, QueryKinds as t };