@stainless-api/docs 0.1.0-beta.92 → 0.1.0-beta.94
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/CHANGELOG.md +21 -0
- package/eslint-suppressions.json +0 -5
- package/package.json +3 -3
- package/plugin/buildAlgoliaIndex.ts +12 -43
- package/plugin/components/SDKSelect.astro +3 -6
- package/plugin/helpers/generateDocsRoutes.ts +32 -0
- package/plugin/helpers/multiSpec.ts +8 -0
- package/plugin/index.ts +53 -46
- package/plugin/loadPluginConfig.ts +131 -62
- package/plugin/react/Routing.tsx +2 -4
- package/plugin/routes/Docs.astro +5 -2
- package/plugin/routes/DocsStatic.astro +2 -4
- package/plugin/routes/Overview.astro +21 -7
- package/plugin/routes/markdown.ts +4 -4
- package/plugin/specs/FileCache.ts +99 -0
- package/plugin/specs/fetchSpecSSR.ts +16 -10
- package/plugin/specs/generateSpec.ts +88 -26
- package/plugin/specs/index.ts +88 -195
- package/plugin/specs/inputResolver.ts +146 -0
- package/virtual-module.d.ts +19 -3
- package/plugin/helpers/getDocsLanguages.ts +0 -9
package/plugin/specs/index.ts
CHANGED
|
@@ -1,202 +1,77 @@
|
|
|
1
|
-
import
|
|
2
|
-
import { mkdir, readdir, readFile, rm, writeFile } from 'fs/promises';
|
|
1
|
+
import { mkdir } from 'fs/promises';
|
|
3
2
|
import path from 'path';
|
|
4
|
-
import crypto from 'crypto';
|
|
5
3
|
|
|
6
|
-
import type * as VirtualManifestModule from 'virtual:stainless-
|
|
4
|
+
import type * as VirtualManifestModule from 'virtual:stainless-apis-manifest';
|
|
7
5
|
|
|
8
6
|
import { makeAsyncVirtualModPlugin } from '../../shared/virtualModule';
|
|
9
7
|
|
|
10
|
-
import { NormalizedStainlessStarlightConfig,
|
|
8
|
+
import { NormalizedStainlessStarlightConfig, ResolvedAPIConfigEntry } from '../loadPluginConfig';
|
|
11
9
|
|
|
12
|
-
import {
|
|
13
|
-
import previewWorkerCode from '../vendor/preview.worker.docs.js?raw';
|
|
14
|
-
import { DocsLanguage } from '@stainless-api/docs-ui/routing';
|
|
10
|
+
import { specCache, SpecCacheResult } from './generateSpec';
|
|
15
11
|
import { AstroIntegrationLogger } from 'astro';
|
|
16
|
-
import
|
|
17
|
-
|
|
18
|
-
type VirtualManifestModuleType = typeof VirtualManifestModule;
|
|
19
|
-
|
|
20
|
-
async function cleanupSpecsDirectory({
|
|
21
|
-
directory,
|
|
22
|
-
keep,
|
|
23
|
-
logger,
|
|
24
|
-
}: {
|
|
25
|
-
directory: string;
|
|
26
|
-
keep: string[];
|
|
27
|
-
logger: AstroIntegrationLogger;
|
|
28
|
-
}) {
|
|
29
|
-
const files = await readdir(directory);
|
|
30
|
-
const filesToDelete = files.filter((file) => !keep.includes(file));
|
|
31
|
-
|
|
32
|
-
if (filesToDelete.length > 0) {
|
|
33
|
-
await Promise.all(filesToDelete.map((file) => rm(path.join(directory, file))));
|
|
34
|
-
logger.info(`Removed ${filesToDelete.length} unused SDKJSON file(s)`);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
12
|
+
import type * as SDKJSON from '@stainless/sdk-json';
|
|
37
13
|
|
|
38
|
-
type
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
versions: Record<DocsLanguage, string> | null;
|
|
42
|
-
project: string;
|
|
14
|
+
export type LoadedAPIConfigEntry = Omit<ResolvedAPIConfigEntry, 'loadSpecs'> & {
|
|
15
|
+
specs: SpecCacheResult[];
|
|
16
|
+
languages: SDKJSON.SpecLanguage[];
|
|
43
17
|
};
|
|
44
18
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
.split('')
|
|
57
|
-
.map((char, index) => (index < 10 ? char : '*'))
|
|
58
|
-
.join('');
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
async function resolveFileInputs(
|
|
62
|
-
inputs: Extract<SDKJSONInputs, { kind: 'file_inputs' }>,
|
|
63
|
-
logger: AstroIntegrationLogger,
|
|
64
|
-
) {
|
|
65
|
-
try {
|
|
66
|
-
const oasStr = await readFile(inputs.oasPath, 'utf8');
|
|
67
|
-
const configStr = await readFile(inputs.configPath, 'utf8');
|
|
68
|
-
return {
|
|
69
|
-
inputs,
|
|
70
|
-
resolved: {
|
|
71
|
-
oasStr,
|
|
72
|
-
configStr,
|
|
73
|
-
versions: null,
|
|
74
|
-
project: inputs.project,
|
|
75
|
-
},
|
|
76
|
-
};
|
|
77
|
-
} catch (error) {
|
|
78
|
-
logger.error(bold('Failed to read file inputs:'));
|
|
79
|
-
logger.error(error instanceof Error ? error.message : 'Unknown error');
|
|
80
|
-
process.exit(1);
|
|
19
|
+
/**
|
|
20
|
+
* A helper class to manage multiple spec cache results for a single API
|
|
21
|
+
* An API may have multiple spec cache results if it has multiple languages
|
|
22
|
+
* Note that one spec may contain multiple languages.
|
|
23
|
+
* */
|
|
24
|
+
export class SpecComposite {
|
|
25
|
+
private languages: Set<SDKJSON.SpecLanguage>;
|
|
26
|
+
private readonly specs: Partial<Record<SDKJSON.SpecLanguage, SpecCacheResult>>;
|
|
27
|
+
|
|
28
|
+
public getLanguages() {
|
|
29
|
+
return Array.from(this.languages);
|
|
81
30
|
}
|
|
82
|
-
}
|
|
83
31
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
try {
|
|
89
|
-
const client = new Stainless({ apiKey: inputs.apiKey.value });
|
|
90
|
-
const configs = await client.projects.configs.retrieve({
|
|
91
|
-
project: inputs.project,
|
|
92
|
-
branch: inputs.branch,
|
|
93
|
-
include: 'openapi',
|
|
94
|
-
});
|
|
95
|
-
const versions = await versionInfo(inputs.project, inputs.apiKey.value);
|
|
96
|
-
|
|
97
|
-
const configYML = Object.values(configs)[0] as { content: unknown };
|
|
98
|
-
const oasJson = Object.values(configs)[1] as { content: unknown };
|
|
99
|
-
const oasStr = oasJson['content'];
|
|
100
|
-
const configStr = configYML['content'];
|
|
101
|
-
|
|
102
|
-
if (typeof oasStr !== 'string' || typeof configStr !== 'string') {
|
|
103
|
-
throw new Error('Received invalid OAS or config from Stainless');
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
return {
|
|
107
|
-
inputs,
|
|
108
|
-
resolved: {
|
|
109
|
-
versions,
|
|
110
|
-
oasStr,
|
|
111
|
-
configStr,
|
|
112
|
-
project: inputs.project,
|
|
113
|
-
},
|
|
114
|
-
};
|
|
115
|
-
} catch (error) {
|
|
116
|
-
logger.error(bold('Failed to fetch API reference information from Stainless:'));
|
|
117
|
-
if (error instanceof APIError && error.status >= 400 && error.status < 500) {
|
|
118
|
-
logger.error(`Requested project slug: "${inputs.project}"`);
|
|
119
|
-
logger.error(`API key: "${redactApiKey(inputs.apiKey.value)}"`);
|
|
120
|
-
logger.error(
|
|
121
|
-
`This error can usually be corrected by re-authenticating with the Stainless. Use the CLI (stl auth login) or verify that the Stainless API key you're using can access the project mentioned above.`,
|
|
122
|
-
);
|
|
123
|
-
} else {
|
|
124
|
-
logger.error(error instanceof Error ? error.message : 'Unknown error');
|
|
32
|
+
public getByLanguage(language: SDKJSON.SpecLanguage) {
|
|
33
|
+
const spec = this.specs[language];
|
|
34
|
+
if (!spec) {
|
|
35
|
+
throw new Error(`Spec for language ${language} not found`);
|
|
125
36
|
}
|
|
126
|
-
|
|
127
|
-
process.exit(1);
|
|
37
|
+
return spec;
|
|
128
38
|
}
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
async function resolveStringInputs(inputs: Extract<SDKJSONInputs, { kind: 'string_inputs' }>) {
|
|
132
|
-
return {
|
|
133
|
-
inputs,
|
|
134
|
-
resolved: {
|
|
135
|
-
oasStr: inputs.oasStr,
|
|
136
|
-
configStr: inputs.configStr,
|
|
137
|
-
versions: null,
|
|
138
|
-
project: inputs.project,
|
|
139
|
-
},
|
|
140
|
-
};
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
async function resolveSpecInputs(
|
|
144
|
-
inputs: SDKJSONInputs,
|
|
145
|
-
logger: AstroIntegrationLogger,
|
|
146
|
-
): Promise<{ inputs: SDKJSONInputs; resolved: ResolvedSpecInputs }> {
|
|
147
|
-
if (inputs.kind === 'file_inputs') return resolveFileInputs(inputs, logger);
|
|
148
|
-
if (inputs.kind === 'stainless_api_inputs') return resolveStainlessApiInputs(inputs, logger);
|
|
149
|
-
if (inputs.kind === 'string_inputs') return resolveStringInputs(inputs);
|
|
150
|
-
throw new Error(`Unexpected spec inputs: ${JSON.stringify(inputs)}`);
|
|
151
|
-
}
|
|
152
39
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
return null;
|
|
40
|
+
/**
|
|
41
|
+
* Returns all specs. It will return each spec once, even if it has multiple languages.
|
|
42
|
+
* */
|
|
43
|
+
public listUniqueSpecs() {
|
|
44
|
+
const seen = new Set<SpecCacheResult>();
|
|
45
|
+
const unique: SpecCacheResult[] = [];
|
|
46
|
+
for (const spec of Object.values(this.specs)) {
|
|
47
|
+
if (!seen.has(spec)) {
|
|
48
|
+
seen.add(spec);
|
|
49
|
+
unique.push(spec);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return unique;
|
|
167
53
|
}
|
|
168
|
-
}
|
|
169
54
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
specPath,
|
|
176
|
-
spec: cachedSpec,
|
|
177
|
-
};
|
|
55
|
+
public listAllLanguagesAndIncludeSpecs() {
|
|
56
|
+
return this.getLanguages().map((language) => ({
|
|
57
|
+
language,
|
|
58
|
+
spec: this.getByLanguage(language),
|
|
59
|
+
}));
|
|
178
60
|
}
|
|
179
61
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
62
|
+
constructor(specs: SpecCacheResult[]) {
|
|
63
|
+
this.languages = new Set<SDKJSON.SpecLanguage>();
|
|
64
|
+
this.specs = {};
|
|
65
|
+
for (const spec of specs) {
|
|
66
|
+
for (const lang of spec.data.languages) {
|
|
67
|
+
if (this.languages.has(lang)) {
|
|
68
|
+
throw new Error(`Language appears multiple times in the same API: ${lang}`);
|
|
69
|
+
}
|
|
70
|
+
this.languages.add(lang);
|
|
71
|
+
this.specs[lang] = spec;
|
|
72
|
+
}
|
|
190
73
|
}
|
|
191
74
|
}
|
|
192
|
-
|
|
193
|
-
await writeFile(specPath, JSON.stringify(sdkJson), 'utf8');
|
|
194
|
-
|
|
195
|
-
return {
|
|
196
|
-
result: 'generated' as const,
|
|
197
|
-
spec: sdkJson,
|
|
198
|
-
specPath,
|
|
199
|
-
};
|
|
200
75
|
}
|
|
201
76
|
|
|
202
77
|
/** Runs once in the build process */
|
|
@@ -207,31 +82,49 @@ export async function startSpecLoader(
|
|
|
207
82
|
) {
|
|
208
83
|
const specsDirectory = path.join(codegenDir.pathname, 'specs');
|
|
209
84
|
await mkdir(specsDirectory, { recursive: true });
|
|
210
|
-
// TODO: can this promise also be deferred until after this function resolves? can this whole
|
|
211
|
-
// function return synchronously?
|
|
212
|
-
// TODO: arena to remember the conceptual reason why he didn’t want this
|
|
213
|
-
const resolvedSpecInputs = await resolveSpecInputs(pluginConfig.specInputs, logger);
|
|
214
85
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
86
|
+
logger.debug(`Setting cache directory to ${specsDirectory}`);
|
|
87
|
+
|
|
88
|
+
// 🚨 Important! You cannot call loadSpecs() before setting the cache directory.
|
|
89
|
+
specCache.setCacheDirectory(specsDirectory);
|
|
218
90
|
|
|
219
|
-
|
|
91
|
+
async function load() {
|
|
92
|
+
const specs = await pluginConfig.api.loadSpecs();
|
|
93
|
+
|
|
94
|
+
// not awaited since it's just cleanup
|
|
95
|
+
specCache.cleanupUnusedFiles().then((result) => {
|
|
96
|
+
if (result.deletedCount > 0) {
|
|
97
|
+
logger.info(`Cleaned up ${result.deletedCount} unused spec files`);
|
|
98
|
+
} else {
|
|
99
|
+
logger.debug(`No unused spec files to clean up`);
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
specComposite: new SpecComposite(specs),
|
|
105
|
+
};
|
|
106
|
+
}
|
|
220
107
|
|
|
221
|
-
|
|
222
|
-
cleanupSpecsDirectory({ directory: specsDirectory, keep: [specFileName], logger });
|
|
108
|
+
const specPromise = load();
|
|
223
109
|
|
|
224
110
|
return {
|
|
225
111
|
specPromise,
|
|
226
112
|
// this virtual module only resolves when the spec is generated
|
|
227
113
|
// this prevents the SSR module from trying to read the spec file before it's generated
|
|
228
|
-
|
|
229
|
-
'virtual:stainless-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
return {
|
|
233
|
-
|
|
234
|
-
|
|
114
|
+
vitePlugins: [
|
|
115
|
+
makeAsyncVirtualModPlugin<typeof VirtualManifestModule>('virtual:stainless-apis-manifest', async () => {
|
|
116
|
+
const api = await specPromise;
|
|
117
|
+
|
|
118
|
+
return {
|
|
119
|
+
api: {
|
|
120
|
+
languages: api.specComposite.listAllLanguagesAndIncludeSpecs().map((langSpec) => ({
|
|
121
|
+
language: langSpec.language,
|
|
122
|
+
sdkJSONFilePath: langSpec.spec.filePath,
|
|
123
|
+
})),
|
|
124
|
+
},
|
|
125
|
+
};
|
|
126
|
+
}),
|
|
127
|
+
],
|
|
235
128
|
};
|
|
236
129
|
}
|
|
237
130
|
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { DocsLanguage } from '@stainless-api/docs-ui/routing';
|
|
2
|
+
import { readFile } from 'fs/promises';
|
|
3
|
+
import { AstroIntegrationLogger } from 'astro';
|
|
4
|
+
import { bold } from '../../shared/terminalUtils';
|
|
5
|
+
import type { LanguageGenerateQuery, LoadedApiKey } from '../loadPluginConfig';
|
|
6
|
+
import Stainless, { APIError } from '@stainless-api/sdk';
|
|
7
|
+
import { GenerateSpecRawInputs } from './generateSpec';
|
|
8
|
+
|
|
9
|
+
export type SpecInputResolver = {
|
|
10
|
+
resolve: (context: { apiKey: LoadedApiKey | null }) => Promise<GenerateSpecRawInputs>;
|
|
11
|
+
printError: (error: Error, logger: AstroIntegrationLogger) => void;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
function fromFiles({
|
|
15
|
+
oasPath,
|
|
16
|
+
configPath,
|
|
17
|
+
languageOverrides,
|
|
18
|
+
stainlessProject,
|
|
19
|
+
}: {
|
|
20
|
+
oasPath: string;
|
|
21
|
+
configPath: string;
|
|
22
|
+
languageOverrides: LanguageGenerateQuery | null;
|
|
23
|
+
stainlessProject: string;
|
|
24
|
+
}): SpecInputResolver {
|
|
25
|
+
return {
|
|
26
|
+
resolve: async () => {
|
|
27
|
+
const oasStr = await readFile(oasPath, 'utf8');
|
|
28
|
+
const configStr = await readFile(configPath, 'utf8');
|
|
29
|
+
return {
|
|
30
|
+
oasStr,
|
|
31
|
+
configStr,
|
|
32
|
+
versionInfo: null,
|
|
33
|
+
languageOverrides,
|
|
34
|
+
stainlessProject,
|
|
35
|
+
};
|
|
36
|
+
},
|
|
37
|
+
printError: (error: Error, logger: AstroIntegrationLogger) => {
|
|
38
|
+
logger.error(bold('Failed to resolve spec inputs from files:'));
|
|
39
|
+
logger.error(error.message);
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
async function fetchVersionInfo(project: string, apiKey: string): Promise<Record<DocsLanguage, string>> {
|
|
45
|
+
const data = await fetch(`https://api.stainless.com/api/projects/${project}/package-versions`, {
|
|
46
|
+
headers: { Authorization: `Bearer ${apiKey}` },
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
const content = await data.text();
|
|
50
|
+
return JSON.parse(content) as Record<DocsLanguage, string>;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function redactApiKey(apiKey: string) {
|
|
54
|
+
return apiKey
|
|
55
|
+
.split('')
|
|
56
|
+
.map((char, index) => (index < 10 ? char : '*'))
|
|
57
|
+
.join('');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function fromStainlessApi(inputs: {
|
|
61
|
+
stainlessProject: string;
|
|
62
|
+
branch: string;
|
|
63
|
+
apiKey?: LoadedApiKey;
|
|
64
|
+
languageOverrides: LanguageGenerateQuery | null;
|
|
65
|
+
}): SpecInputResolver {
|
|
66
|
+
let apiKey: string | undefined;
|
|
67
|
+
return {
|
|
68
|
+
async resolve(context) {
|
|
69
|
+
apiKey = context.apiKey?.value ?? inputs.apiKey?.value;
|
|
70
|
+
|
|
71
|
+
if (!apiKey) {
|
|
72
|
+
throw new Error('No API key provided');
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
const client = new Stainless({ apiKey });
|
|
76
|
+
const configs = await client.projects.configs.retrieve({
|
|
77
|
+
project: inputs.stainlessProject,
|
|
78
|
+
branch: inputs.branch,
|
|
79
|
+
include: 'openapi',
|
|
80
|
+
});
|
|
81
|
+
const versionInfo = await fetchVersionInfo(inputs.stainlessProject, apiKey);
|
|
82
|
+
|
|
83
|
+
const configYML = Object.values(configs)[0] as { content: unknown };
|
|
84
|
+
const oasJson = Object.values(configs)[1] as { content: unknown };
|
|
85
|
+
const oasStr = oasJson['content'];
|
|
86
|
+
const configStr = configYML['content'];
|
|
87
|
+
|
|
88
|
+
if (typeof oasStr !== 'string' || typeof configStr !== 'string') {
|
|
89
|
+
throw new Error('Received invalid OAS or config from Stainless');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
return {
|
|
93
|
+
oasStr,
|
|
94
|
+
configStr,
|
|
95
|
+
versionInfo,
|
|
96
|
+
languageOverrides: inputs.languageOverrides,
|
|
97
|
+
stainlessProject: inputs.stainlessProject,
|
|
98
|
+
};
|
|
99
|
+
},
|
|
100
|
+
printError: (error: Error, logger: AstroIntegrationLogger) => {
|
|
101
|
+
if (error instanceof APIError && error.status >= 400 && error.status < 500) {
|
|
102
|
+
logger.error(`Requested project slug: "${inputs.stainlessProject}"`);
|
|
103
|
+
if (apiKey) {
|
|
104
|
+
logger.error(`API key: "${redactApiKey(apiKey)}"`);
|
|
105
|
+
}
|
|
106
|
+
logger.error(
|
|
107
|
+
`This error can usually be corrected by re-authenticating with the Stainless. Use the CLI (stl auth login) or verify that the Stainless API key you're using can access the project mentioned above.`,
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
},
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function fromStrings({
|
|
115
|
+
oasStr,
|
|
116
|
+
configStr,
|
|
117
|
+
languageOverrides,
|
|
118
|
+
stainlessProject,
|
|
119
|
+
}: {
|
|
120
|
+
oasStr: string;
|
|
121
|
+
configStr: string;
|
|
122
|
+
languageOverrides: LanguageGenerateQuery | null;
|
|
123
|
+
stainlessProject: string;
|
|
124
|
+
}): SpecInputResolver {
|
|
125
|
+
return {
|
|
126
|
+
async resolve() {
|
|
127
|
+
return {
|
|
128
|
+
oasStr,
|
|
129
|
+
configStr,
|
|
130
|
+
versionInfo: null,
|
|
131
|
+
languageOverrides,
|
|
132
|
+
stainlessProject,
|
|
133
|
+
};
|
|
134
|
+
},
|
|
135
|
+
printError(error: Error, logger: AstroIntegrationLogger) {
|
|
136
|
+
logger.error(bold('Failed to resolve spec inputs from strings:'));
|
|
137
|
+
logger.error(error.message);
|
|
138
|
+
},
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export const resolveSpec = {
|
|
143
|
+
fromFiles,
|
|
144
|
+
fromStainlessApi,
|
|
145
|
+
fromStrings,
|
|
146
|
+
} satisfies Record<string, (...args: never[]) => SpecInputResolver>;
|
package/virtual-module.d.ts
CHANGED
|
@@ -73,12 +73,28 @@ declare module 'virtual:stl-docs/components/AiChat.tsx' {
|
|
|
73
73
|
export const STAINLESS_PROJECT: string | undefined;
|
|
74
74
|
}
|
|
75
75
|
|
|
76
|
-
declare module 'virtual:stainless-
|
|
77
|
-
|
|
76
|
+
declare module 'virtual:stainless-apis-manifest' {
|
|
77
|
+
import type { DocsLanguage } from '@stainless-api/docs-ui/routing';
|
|
78
|
+
|
|
79
|
+
export type APIManifestEntry = {
|
|
80
|
+
languages: {
|
|
81
|
+
sdkJSONFilePath: string;
|
|
82
|
+
language: DocsLanguage;
|
|
83
|
+
}[];
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export const api: APIManifestEntry;
|
|
78
87
|
}
|
|
79
88
|
|
|
80
89
|
declare module 'virtual:stl-starlight-reference-sidebars' {
|
|
81
90
|
import type { DocsLanguage } from '@stainless-api/docs-ui/routing';
|
|
82
91
|
import type { StarlightRouteData } from '@astrojs/starlight/route-data';
|
|
83
|
-
|
|
92
|
+
|
|
93
|
+
export type GeneratedSidebarDef = {
|
|
94
|
+
id: number;
|
|
95
|
+
language: DocsLanguage;
|
|
96
|
+
entries: StarlightRouteData['sidebar'];
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const sidebars: GeneratedSidebarDef[];
|
|
84
100
|
}
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import { DocsLanguage } from '@stainless-api/docs-ui/routing';
|
|
2
|
-
import type * as SDKJSON from '@stainless/sdk-json';
|
|
3
|
-
|
|
4
|
-
export function getDocsLanguages(spec: SDKJSON.Spec, excludeLanguages: DocsLanguage[]) {
|
|
5
|
-
// TODO: should not force unwrap this
|
|
6
|
-
const languages: DocsLanguage[] = spec.docs!.languages ?? ['http'];
|
|
7
|
-
|
|
8
|
-
return languages.filter((language) => !excludeLanguages.includes(language));
|
|
9
|
-
}
|