@stainless-api/docs 0.1.0-beta.87 → 0.1.0-beta.89
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 +31 -0
- package/eslint-suppressions.json +2 -22
- package/package.json +5 -7
- package/playground-virtual-modules.d.ts +96 -0
- package/plugin/buildAlgoliaIndex.ts +9 -7
- package/plugin/components/SDKSelect.astro +19 -17
- package/plugin/components/search/SearchIsland.tsx +4 -4
- package/plugin/globalJs/copy.ts +5 -2
- package/plugin/globalJs/navigation.ts +3 -3
- package/plugin/helpers/getDocsLanguages.ts +9 -0
- package/plugin/index.ts +112 -136
- package/plugin/loadPluginConfig.ts +36 -52
- package/plugin/react/Routing.tsx +5 -5
- package/plugin/referencePlaceholderUtils.ts +17 -14
- package/plugin/replaceSidebarPlaceholderMiddleware.ts +38 -31
- package/plugin/routes/Docs.astro +2 -2
- package/plugin/routes/DocsStatic.astro +2 -2
- package/plugin/routes/Overview.astro +2 -2
- package/plugin/routes/markdown.ts +3 -3
- package/plugin/{cms → sidebar-utils}/sidebar-builder.ts +10 -18
- package/plugin/specs/fetchSpecSSR.ts +21 -0
- package/plugin/specs/generateSpec.ts +50 -0
- package/plugin/specs/index.ts +238 -0
- package/shared/virtualModule.ts +54 -1
- package/stl-docs/components/Head.astro +4 -4
- package/stl-docs/components/sidebars/convertAstroSidebarToStl.tsx +32 -16
- package/stl-docs/fonts.ts +172 -0
- package/stl-docs/index.ts +7 -4
- package/stl-docs/loadStlDocsConfig.ts +4 -1
- package/stl-docs/proseMarkdown/proseMarkdownMiddleware.ts +3 -1
- package/theme.css +0 -1
- package/virtual-module.d.ts +23 -100
- package/plugin/cms/client.ts +0 -62
- package/plugin/cms/generate-spec.ts +0 -112
- package/plugin/cms/server.ts +0 -364
- package/styles/fonts.css +0 -83
- /package/plugin/{cms → specs}/worker.ts +0 -0
package/plugin/index.ts
CHANGED
|
@@ -1,27 +1,26 @@
|
|
|
1
1
|
import react from '@astrojs/react';
|
|
2
2
|
import type { StarlightPlugin } from '@astrojs/starlight/types';
|
|
3
|
-
import type { AstroIntegration
|
|
3
|
+
import type { AstroIntegration } from 'astro';
|
|
4
4
|
import type { BundledTheme } from 'shiki';
|
|
5
5
|
import { config } from 'dotenv';
|
|
6
|
-
import getPort from 'get-port';
|
|
7
|
-
import { DevSpecServer, startDevServer, type SpecResp } from './cms/server';
|
|
8
6
|
import { buildAlgoliaIndex } from './buildAlgoliaIndex';
|
|
9
7
|
import {
|
|
10
8
|
getAPIReferencePlaceholderItemFromSidebarConfig,
|
|
11
9
|
makePlaceholderItems,
|
|
12
10
|
} from './referencePlaceholderUtils';
|
|
13
|
-
import
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
11
|
+
import {
|
|
12
|
+
SidebarConfigItemsBuilder,
|
|
13
|
+
toStarlightSidebar,
|
|
14
|
+
type GeneratedSidebarConfig,
|
|
15
|
+
type ReferenceSidebarConfigGenerateOptions,
|
|
16
|
+
type ReferenceSidebarConfigItem,
|
|
17
|
+
} from './sidebar-utils/sidebar-builder';
|
|
18
18
|
import {
|
|
19
19
|
parseStarlightPluginConfig,
|
|
20
20
|
type NormalizedStainlessStarlightConfig,
|
|
21
21
|
type SomeStainlessStarlightUserConfig,
|
|
22
|
-
type SpecRetrieverConfig,
|
|
23
22
|
} from './loadPluginConfig';
|
|
24
|
-
import { buildVirtualModuleString } from '../shared/virtualModule';
|
|
23
|
+
import { buildVirtualModuleString, makeAsyncVirtualModPlugin } from '../shared/virtualModule';
|
|
25
24
|
import type * as StlStarlightVirtualModule from 'virtual:stl-starlight-virtual-module';
|
|
26
25
|
import path from 'path';
|
|
27
26
|
import fs from 'fs';
|
|
@@ -30,6 +29,10 @@ import { resolveSrcFile } from '../resolveSrcFile';
|
|
|
30
29
|
import { mkdir, writeFile } from 'fs/promises';
|
|
31
30
|
import { fileURLToPath } from 'url';
|
|
32
31
|
import prebundleWorkers from 'vite-plugin-prebundle-workers';
|
|
32
|
+
import { SpecLoader, startSpecLoader } from './specs';
|
|
33
|
+
|
|
34
|
+
import type * as ReferenceSidebarsVirtualModule from 'virtual:stl-starlight-reference-sidebars';
|
|
35
|
+
import { getDocsLanguages } from './helpers/getDocsLanguages';
|
|
33
36
|
import { generateMissingRouteList } from '@stainless-api/docs-ui/routing';
|
|
34
37
|
|
|
35
38
|
export { generateAPILink } from './generateAPIReferenceLink';
|
|
@@ -88,37 +91,8 @@ export function generateAPIReferenceItems(
|
|
|
88
91
|
return makePlaceholderItems(id);
|
|
89
92
|
}
|
|
90
93
|
|
|
91
|
-
function tmpGetCMSServerConfig(specRetrieverConfig: SpecRetrieverConfig) {
|
|
92
|
-
if (specRetrieverConfig.kind === 'external_spec_server') {
|
|
93
|
-
throw new Error('External spec server is not yet supported');
|
|
94
|
-
}
|
|
95
|
-
if (specRetrieverConfig.kind === 'local_spec_server_with_files') {
|
|
96
|
-
if (!specRetrieverConfig.apiKey) {
|
|
97
|
-
throw new Error('API key is required');
|
|
98
|
-
}
|
|
99
|
-
return {
|
|
100
|
-
apiKey: specRetrieverConfig.apiKey,
|
|
101
|
-
version: specRetrieverConfig.version,
|
|
102
|
-
devPaths: specRetrieverConfig.devPaths,
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (specRetrieverConfig.kind === 'local_spec_server_with_remote_files') {
|
|
107
|
-
return {
|
|
108
|
-
apiKey: specRetrieverConfig.apiKey,
|
|
109
|
-
version: specRetrieverConfig.version,
|
|
110
|
-
devPaths: {
|
|
111
|
-
oasPath: undefined,
|
|
112
|
-
configPath: undefined,
|
|
113
|
-
},
|
|
114
|
-
};
|
|
115
|
-
}
|
|
116
|
-
throw new Error('Invalid spec retriever config');
|
|
117
|
-
}
|
|
118
|
-
|
|
119
94
|
async function stlStarlightAstroIntegration(
|
|
120
95
|
pluginConfig: NormalizedStainlessStarlightConfig,
|
|
121
|
-
stlStarlightPluginLogger: AstroIntegrationLogger,
|
|
122
96
|
): Promise<AstroIntegration> {
|
|
123
97
|
const virtualId = `virtual:stl-starlight-virtual-module`;
|
|
124
98
|
// The '\0' prefix tells Vite “this is a virtual module” and prevents it from being resolved again.
|
|
@@ -127,11 +101,15 @@ async function stlStarlightAstroIntegration(
|
|
|
127
101
|
let buildPlaygrounds;
|
|
128
102
|
let astroBase = '/';
|
|
129
103
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
104
|
+
let specLoader: SpecLoader | undefined;
|
|
105
|
+
async function getSpec() {
|
|
106
|
+
if (!specLoader) throw new Error('Expected spec loader to exist');
|
|
107
|
+
const result = await specLoader.specPromise;
|
|
108
|
+
return {
|
|
109
|
+
spec: result.spec.data,
|
|
110
|
+
auth: result.spec.auth,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
135
113
|
|
|
136
114
|
let building: Promise<void> | undefined;
|
|
137
115
|
let reportError: ((message: string) => void) | null = null;
|
|
@@ -141,17 +119,9 @@ async function stlStarlightAstroIntegration(
|
|
|
141
119
|
if (!pluginConfig.experimentalPlaygrounds) return;
|
|
142
120
|
if (building) return building;
|
|
143
121
|
return (building = (async () => {
|
|
144
|
-
const {
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
body: JSON.stringify({}),
|
|
148
|
-
})
|
|
149
|
-
).json()) as SpecResp;
|
|
150
|
-
if (!spec || !auth) throw new Error('expected spec');
|
|
151
|
-
|
|
152
|
-
const langs = (spec.docs?.languages ?? ['http']).filter(
|
|
153
|
-
(lang) => !pluginConfig.excludeLanguages?.includes(lang),
|
|
154
|
-
);
|
|
122
|
+
const { spec, auth } = await getSpec();
|
|
123
|
+
|
|
124
|
+
const langs = getDocsLanguages(spec, pluginConfig.excludeLanguages);
|
|
155
125
|
|
|
156
126
|
await buildPlaygrounds!({
|
|
157
127
|
spec,
|
|
@@ -180,28 +150,13 @@ async function stlStarlightAstroIntegration(
|
|
|
180
150
|
const projectDir = astroConfig.root.pathname;
|
|
181
151
|
astroBase = astroConfig.base;
|
|
182
152
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
cmsServer = startDevServer({
|
|
192
|
-
port: CMS_PORT,
|
|
193
|
-
apiKey: apiKey.value,
|
|
194
|
-
version,
|
|
195
|
-
devPaths,
|
|
196
|
-
logger: stlStarlightPluginLogger,
|
|
197
|
-
specCacheDirectory,
|
|
198
|
-
getGeneratedSidebarConfig: (id: number) => {
|
|
199
|
-
const config = sidebarConfigs.get(id);
|
|
200
|
-
if (!config) {
|
|
201
|
-
return null;
|
|
202
|
-
}
|
|
203
|
-
return config;
|
|
204
|
-
},
|
|
153
|
+
specLoader = await startSpecLoader(pluginConfig, logger, createCodegenDir());
|
|
154
|
+
specLoader.specPromise.then((specResult) => {
|
|
155
|
+
if (specResult.result === 'generated') {
|
|
156
|
+
logger.info(`Generated new SDKJSON`);
|
|
157
|
+
} else if (specResult.result === 'exists') {
|
|
158
|
+
logger.info(`Loaded SDKJSON`);
|
|
159
|
+
}
|
|
205
160
|
});
|
|
206
161
|
|
|
207
162
|
reportError = (message: string) => logger.error(message);
|
|
@@ -240,6 +195,55 @@ async function stlStarlightAstroIntegration(
|
|
|
240
195
|
updateConfig({
|
|
241
196
|
vite: {
|
|
242
197
|
plugins: [
|
|
198
|
+
makeAsyncVirtualModPlugin<typeof ReferenceSidebarsVirtualModule>(
|
|
199
|
+
'virtual:stl-starlight-reference-sidebars',
|
|
200
|
+
async () => {
|
|
201
|
+
const { spec } = await getSpec();
|
|
202
|
+
const languages = getDocsLanguages(spec, pluginConfig.excludeLanguages);
|
|
203
|
+
|
|
204
|
+
const sidebars = [...sidebarConfigs.entries()]
|
|
205
|
+
// produce all { id, language } combos with the attached config
|
|
206
|
+
// flattens to one item per language * id combo
|
|
207
|
+
.flatMap(([id, config]) =>
|
|
208
|
+
languages.map((language) => ({
|
|
209
|
+
id,
|
|
210
|
+
config,
|
|
211
|
+
language,
|
|
212
|
+
})),
|
|
213
|
+
)
|
|
214
|
+
// produce a sidebar for each
|
|
215
|
+
// later we will .find() the sidebar that matches the (id, language)
|
|
216
|
+
.map(({ id, config, language }) => {
|
|
217
|
+
const configItemsBuilder = new SidebarConfigItemsBuilder(
|
|
218
|
+
spec,
|
|
219
|
+
language,
|
|
220
|
+
config.options,
|
|
221
|
+
);
|
|
222
|
+
|
|
223
|
+
let userSidebarConfig = configItemsBuilder.generateItems();
|
|
224
|
+
if (config.transformFn) {
|
|
225
|
+
const transformedSidebarConfig = config.transformFn(userSidebarConfig, language);
|
|
226
|
+
if (transformedSidebarConfig) userSidebarConfig = transformedSidebarConfig;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
return {
|
|
230
|
+
id,
|
|
231
|
+
language,
|
|
232
|
+
// this has to run multpile times because it depends on the
|
|
233
|
+
// userSidebarConfig (which is per-id) and the language
|
|
234
|
+
entries: toStarlightSidebar({
|
|
235
|
+
basePath: path.posix.join(astroBase, pluginConfig.basePath), // TODO, is this right?
|
|
236
|
+
spec,
|
|
237
|
+
entries: userSidebarConfig,
|
|
238
|
+
currentLanguage: language,
|
|
239
|
+
}),
|
|
240
|
+
};
|
|
241
|
+
});
|
|
242
|
+
|
|
243
|
+
return { sidebars };
|
|
244
|
+
},
|
|
245
|
+
),
|
|
246
|
+
specLoader.vitePlugin,
|
|
243
247
|
{
|
|
244
248
|
name: 'stl-starlight-vite',
|
|
245
249
|
buildStart() {
|
|
@@ -251,23 +255,7 @@ async function stlStarlightAstroIntegration(
|
|
|
251
255
|
.buildPlaygrounds;
|
|
252
256
|
}
|
|
253
257
|
|
|
254
|
-
for (
|
|
255
|
-
if (!filePath) {
|
|
256
|
-
continue;
|
|
257
|
-
}
|
|
258
|
-
server.watcher.add(filePath);
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
server.watcher.on('change', async (changed) => {
|
|
262
|
-
if (Object.values(devPaths).includes(changed)) {
|
|
263
|
-
logger.info(`${changed} changed, reloading...`);
|
|
264
|
-
cmsServer?.invalidate();
|
|
265
|
-
server.hot.send({
|
|
266
|
-
type: 'full-reload',
|
|
267
|
-
path: '*',
|
|
268
|
-
});
|
|
269
|
-
}
|
|
270
|
-
});
|
|
258
|
+
// TODO: eventually - re-add support for watching local input changes (eg. reloading when OAS/config files change)
|
|
271
259
|
},
|
|
272
260
|
resolveId(id) {
|
|
273
261
|
if (id === virtualId) {
|
|
@@ -312,9 +300,8 @@ async function stlStarlightAstroIntegration(
|
|
|
312
300
|
if (id === resolvedId) {
|
|
313
301
|
return [
|
|
314
302
|
buildVirtualModuleString({
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
EXCLUDE_LANGUAGES: ['php', ...pluginConfig.excludeLanguages],
|
|
303
|
+
RESOLVED_API_REFERENCE_PATH: path.posix.join(astroConfig.base, pluginConfig.basePath),
|
|
304
|
+
EXCLUDE_LANGUAGES: pluginConfig.excludeLanguages,
|
|
318
305
|
DEFAULT_LANGUAGE: pluginConfig.defaultLanguage,
|
|
319
306
|
BREADCRUMB_CONFIG: pluginConfig.breadcrumbs,
|
|
320
307
|
EXPAND_RESOURCES: pluginConfig.expandResources,
|
|
@@ -327,7 +314,7 @@ async function stlStarlightAstroIntegration(
|
|
|
327
314
|
ENABLE_CONTEXT_MENU: pluginConfig.contextMenu,
|
|
328
315
|
EXPERIMENTAL_PLAYGROUNDS: !!pluginConfig.experimentalPlaygrounds,
|
|
329
316
|
EXPERIMENTAL_REQUEST_BUILDER: pluginConfig.experimentalRequestBuilder,
|
|
330
|
-
STAINLESS_PROJECT:
|
|
317
|
+
STAINLESS_PROJECT: pluginConfig.specInputs.project,
|
|
331
318
|
} satisfies Omit<typeof StlStarlightVirtualModule, 'MIDDLEWARE'>),
|
|
332
319
|
vmMiddlewareExport,
|
|
333
320
|
].join('\n');
|
|
@@ -353,9 +340,6 @@ async function stlStarlightAstroIntegration(
|
|
|
353
340
|
},
|
|
354
341
|
});
|
|
355
342
|
},
|
|
356
|
-
'astro:server:done': async () => {
|
|
357
|
-
await cmsServer?.destroy();
|
|
358
|
-
},
|
|
359
343
|
'astro:build:start'({ logger }) {
|
|
360
344
|
collectedErrors = [];
|
|
361
345
|
reportError = (message: string) => {
|
|
@@ -384,25 +368,16 @@ async function stlStarlightAstroIntegration(
|
|
|
384
368
|
// Instead of showing a generic 404, we statically generate pages for these routes and mark them
|
|
385
369
|
// in this file so Cloudflare can serve them with a 404 status. These pages display helpful information
|
|
386
370
|
// about the missing method and provide links to SDKs where it is available.
|
|
387
|
-
const {
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
});
|
|
398
|
-
await mkdir(stainlessDir, { recursive: true });
|
|
399
|
-
await writeFile(
|
|
400
|
-
path.join(stainlessDir, 'missing-routes.json'),
|
|
401
|
-
JSON.stringify(missingRoutes, null, 2),
|
|
402
|
-
);
|
|
403
|
-
} else {
|
|
404
|
-
console.log('Could not retrieve spec for missing routes check');
|
|
405
|
-
}
|
|
371
|
+
const { spec } = await getSpec();
|
|
372
|
+
const missingRoutes = generateMissingRouteList({
|
|
373
|
+
spec,
|
|
374
|
+
basePath: path.posix.join(astroBase, pluginConfig.basePath),
|
|
375
|
+
});
|
|
376
|
+
await mkdir(stainlessDir, { recursive: true });
|
|
377
|
+
await writeFile(
|
|
378
|
+
path.join(stainlessDir, 'missing-routes.json'),
|
|
379
|
+
JSON.stringify(missingRoutes, null, 2),
|
|
380
|
+
);
|
|
406
381
|
},
|
|
407
382
|
},
|
|
408
383
|
};
|
|
@@ -444,40 +419,41 @@ export function stainlessStarlight(someUserConfig: SomeStainlessStarlightUserCon
|
|
|
444
419
|
addIntegration(react());
|
|
445
420
|
}
|
|
446
421
|
|
|
447
|
-
if ('apiKey' in config.
|
|
448
|
-
if (!config.
|
|
422
|
+
if ('apiKey' in config.specInputs) {
|
|
423
|
+
if (!config.specInputs.apiKey) {
|
|
449
424
|
logger.info(`Stainless credentials not loaded`);
|
|
450
|
-
} else if (config.
|
|
425
|
+
} else if (config.specInputs.apiKey.source === 'explicit-config') {
|
|
451
426
|
logger.info(`Stainless credentials loaded from user config`);
|
|
452
|
-
} else if (config.
|
|
427
|
+
} else if (config.specInputs.apiKey.source === 'environment-variable') {
|
|
453
428
|
logger.info('Stainless credentials loaded from `STAINLESS_API_KEY` environment variable');
|
|
454
|
-
} else if (config.
|
|
429
|
+
} else if (config.specInputs.apiKey.source === 'cli') {
|
|
455
430
|
logger.info('Stainless credentials loaded from `stl` CLI');
|
|
456
431
|
}
|
|
457
432
|
}
|
|
458
433
|
|
|
459
|
-
if (
|
|
460
|
-
command === 'build' &&
|
|
461
|
-
config.specRetrieverConfig.kind === 'local_spec_server_with_remote_files'
|
|
462
|
-
) {
|
|
434
|
+
if (command === 'build' && config.specInputs.kind === 'stainless_api_inputs') {
|
|
463
435
|
await buildAlgoliaIndex({
|
|
464
|
-
|
|
465
|
-
|
|
436
|
+
stainlessProject: config.specInputs.project,
|
|
437
|
+
branch: config.specInputs.branch,
|
|
438
|
+
apiKey: config.specInputs.apiKey.value,
|
|
466
439
|
logger,
|
|
467
440
|
});
|
|
468
441
|
}
|
|
469
442
|
|
|
470
|
-
addIntegration(await stlStarlightAstroIntegration(config, logger));
|
|
471
|
-
|
|
472
443
|
if (starlightConfig.sidebar) {
|
|
473
444
|
// for pagination (https://starlight.astro.build/reference/configuration/#pagination) to work correctly
|
|
474
445
|
// update the placeholder link to be correct
|
|
475
|
-
const
|
|
476
|
-
|
|
477
|
-
|
|
446
|
+
for (const placeholder of getAPIReferencePlaceholderItemFromSidebarConfig(
|
|
447
|
+
starlightConfig.sidebar,
|
|
448
|
+
)) {
|
|
449
|
+
if (placeholder && typeof placeholder === 'object' && 'link' in placeholder) {
|
|
450
|
+
placeholder.link = config.basePath;
|
|
451
|
+
}
|
|
478
452
|
}
|
|
479
453
|
}
|
|
480
454
|
|
|
455
|
+
addIntegration(await stlStarlightAstroIntegration(config));
|
|
456
|
+
|
|
481
457
|
const expressiveCodeConfig =
|
|
482
458
|
typeof starlightConfig.expressiveCode === 'object' ? starlightConfig.expressiveCode : {};
|
|
483
459
|
|
|
@@ -5,7 +5,6 @@ import { existsSync, readFileSync } from 'fs';
|
|
|
5
5
|
import type { CreateShikiHighlighterOptions } from '@astrojs/markdown-remark';
|
|
6
6
|
import type { DocsLanguage } from '@stainless-api/docs-ui/routing';
|
|
7
7
|
import type { PropertySettingsType } from '@stainless-api/docs-ui/contexts';
|
|
8
|
-
import type { InputFilePaths } from '../plugin/cms/server';
|
|
9
8
|
import { bold } from '../shared/terminalUtils';
|
|
10
9
|
|
|
11
10
|
export type AstroCommand = 'dev' | 'build' | 'preview' | 'sync';
|
|
@@ -158,7 +157,7 @@ function resolvePath(inputPath: string) {
|
|
|
158
157
|
return path.resolve(process.cwd(), inputPath);
|
|
159
158
|
}
|
|
160
159
|
|
|
161
|
-
function getLocalFilePaths(command: AstroCommand)
|
|
160
|
+
function getLocalFilePaths(command: AstroCommand) {
|
|
162
161
|
if (command !== 'dev') {
|
|
163
162
|
return null;
|
|
164
163
|
}
|
|
@@ -185,26 +184,6 @@ export type LoadedApiKey = {
|
|
|
185
184
|
source: ApiKeySource;
|
|
186
185
|
};
|
|
187
186
|
|
|
188
|
-
export type SpecRetrieverConfig =
|
|
189
|
-
| {
|
|
190
|
-
kind: 'external_spec_server';
|
|
191
|
-
specServerUrl: string;
|
|
192
|
-
stainlessProject: null;
|
|
193
|
-
}
|
|
194
|
-
| {
|
|
195
|
-
kind: 'local_spec_server_with_files';
|
|
196
|
-
stainlessProject: string;
|
|
197
|
-
devPaths: InputFilePaths;
|
|
198
|
-
apiKey: LoadedApiKey | null;
|
|
199
|
-
version: VersionUserConfig;
|
|
200
|
-
}
|
|
201
|
-
| {
|
|
202
|
-
kind: 'local_spec_server_with_remote_files';
|
|
203
|
-
stainlessProject: string;
|
|
204
|
-
apiKey: LoadedApiKey;
|
|
205
|
-
version: VersionUserConfig;
|
|
206
|
-
};
|
|
207
|
-
|
|
208
187
|
function parseAuthJson(authJsonStr: string) {
|
|
209
188
|
let json: unknown;
|
|
210
189
|
try {
|
|
@@ -252,10 +231,31 @@ function loadApiKey(configValue: string | undefined): LoadedApiKey | null {
|
|
|
252
231
|
return { value: accessToken, source: 'cli' };
|
|
253
232
|
}
|
|
254
233
|
|
|
234
|
+
export type SDKJSONInputs =
|
|
235
|
+
| {
|
|
236
|
+
kind: 'file_inputs';
|
|
237
|
+
project: string;
|
|
238
|
+
oasPath: string;
|
|
239
|
+
configPath: string;
|
|
240
|
+
}
|
|
241
|
+
| {
|
|
242
|
+
kind: 'stainless_api_inputs';
|
|
243
|
+
project: string;
|
|
244
|
+
branch: string;
|
|
245
|
+
apiKey: LoadedApiKey;
|
|
246
|
+
}
|
|
247
|
+
| {
|
|
248
|
+
kind: 'string_inputs';
|
|
249
|
+
oasStr: string;
|
|
250
|
+
configStr: string;
|
|
251
|
+
project: string;
|
|
252
|
+
};
|
|
253
|
+
|
|
255
254
|
function normalizeConfig(partial: SomeStainlessStarlightUserConfig, command: AstroCommand) {
|
|
256
255
|
const configWithDefaults = {
|
|
257
256
|
basePath: partial.basePath ?? '/api',
|
|
258
|
-
|
|
257
|
+
// TODO: why are we excluding php; do we need to
|
|
258
|
+
excludeLanguages: ['php' as const, ...(partial.excludeLanguages ?? [])],
|
|
259
259
|
defaultLanguage: partial.defaultLanguage ?? 'http',
|
|
260
260
|
breadcrumbs: {
|
|
261
261
|
includeCurrentPage: partial.breadcrumbs?.includeCurrentPage ?? false,
|
|
@@ -285,38 +285,23 @@ function normalizeConfig(partial: SomeStainlessStarlightUserConfig, command: Ast
|
|
|
285
285
|
experimentalPrerender: partial.experimentalPrerender ?? true,
|
|
286
286
|
};
|
|
287
287
|
|
|
288
|
-
function
|
|
289
|
-
if ('externalSpecServerUrl' in partial) {
|
|
290
|
-
return {
|
|
291
|
-
kind: 'external_spec_server',
|
|
292
|
-
specServerUrl: partial.externalSpecServerUrl,
|
|
293
|
-
stainlessProject: null,
|
|
294
|
-
};
|
|
295
|
-
}
|
|
296
|
-
|
|
288
|
+
function getSpecInputs(): SDKJSONInputs {
|
|
297
289
|
if (!('stainlessProject' in partial)) {
|
|
298
290
|
throw new Error('You must provide a stainlessProject when using Stainless Starlight');
|
|
299
291
|
}
|
|
300
292
|
|
|
301
|
-
const apiKey = loadApiKey(partial.apiKey);
|
|
302
|
-
|
|
303
|
-
const version = {
|
|
304
|
-
stainlessProject: partial.stainlessProject,
|
|
305
|
-
branch: partial.versions?.[0]?.branch ?? 'main',
|
|
306
|
-
version: partial.versions?.[0]?.version ?? 'v1',
|
|
307
|
-
};
|
|
308
|
-
|
|
309
293
|
const localFilePaths = getLocalFilePaths(command);
|
|
310
294
|
if (localFilePaths) {
|
|
311
295
|
return {
|
|
312
|
-
kind: '
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
version,
|
|
296
|
+
kind: 'file_inputs',
|
|
297
|
+
project: partial.stainlessProject,
|
|
298
|
+
oasPath: localFilePaths.oasPath,
|
|
299
|
+
configPath: localFilePaths.configPath,
|
|
317
300
|
};
|
|
318
301
|
}
|
|
319
302
|
|
|
303
|
+
const apiKey = loadApiKey(partial.apiKey);
|
|
304
|
+
|
|
320
305
|
if (!apiKey) {
|
|
321
306
|
throw new Error(
|
|
322
307
|
[
|
|
@@ -329,20 +314,19 @@ function normalizeConfig(partial: SomeStainlessStarlightUserConfig, command: Ast
|
|
|
329
314
|
].join('\n'),
|
|
330
315
|
);
|
|
331
316
|
}
|
|
332
|
-
|
|
333
317
|
return {
|
|
334
|
-
kind: '
|
|
318
|
+
kind: 'stainless_api_inputs',
|
|
319
|
+
project: partial.stainlessProject,
|
|
320
|
+
branch: partial.versions?.[0]?.branch ?? 'main',
|
|
335
321
|
apiKey,
|
|
336
|
-
stainlessProject: partial.stainlessProject,
|
|
337
|
-
version,
|
|
338
322
|
};
|
|
339
323
|
}
|
|
340
324
|
|
|
341
|
-
const
|
|
325
|
+
const specInputs = getSpecInputs();
|
|
342
326
|
|
|
343
327
|
return {
|
|
344
328
|
...configWithDefaults,
|
|
345
|
-
|
|
329
|
+
specInputs,
|
|
346
330
|
};
|
|
347
331
|
}
|
|
348
332
|
|
|
@@ -354,7 +338,7 @@ export type NormalizedStainlessStarlightConfig = ReturnType<typeof normalizeConf
|
|
|
354
338
|
|
|
355
339
|
We've tried to avoid any config values being optional/undefined. To accomplish this:
|
|
356
340
|
- Any optional config values should have their defaults set here: eg. basePath defaults to /api
|
|
357
|
-
- If a field is only used in certain contexts, we make each context a discriminated union (see
|
|
341
|
+
- If a field is only used in certain contexts, we make each context a discriminated union (see SDKJSONInputs)
|
|
358
342
|
- We prefer empty arrays over undefined/null
|
|
359
343
|
*/
|
|
360
344
|
export function parseStarlightPluginConfig(partial: SomeStainlessStarlightUserConfig, command: AstroCommand) {
|
package/plugin/react/Routing.tsx
CHANGED
|
@@ -43,7 +43,7 @@ import {
|
|
|
43
43
|
import { Dropdown } from '@stainless-api/docs/components';
|
|
44
44
|
|
|
45
45
|
import {
|
|
46
|
-
|
|
46
|
+
RESOLVED_API_REFERENCE_PATH,
|
|
47
47
|
EXCLUDE_LANGUAGES,
|
|
48
48
|
EXPAND_RESOURCES,
|
|
49
49
|
HIGHLIGHT_THEMES,
|
|
@@ -282,7 +282,7 @@ export function RenderLibraries({ metadata }: { metadata: SpecMetadata }) {
|
|
|
282
282
|
language={language}
|
|
283
283
|
version={data.version || ''}
|
|
284
284
|
install={data.install || ''}
|
|
285
|
-
links={{ repo: data.repo_url || '#', docs: `${
|
|
285
|
+
links={{ repo: data.repo_url || '#', docs: `${RESOLVED_API_REFERENCE_PATH}/${language}` }}
|
|
286
286
|
/>
|
|
287
287
|
))}
|
|
288
288
|
</ComponentProvider>
|
|
@@ -295,7 +295,7 @@ export function RenderSpecOverview({ spec, language }: { spec: SDKJSON.Spec; lan
|
|
|
295
295
|
return (
|
|
296
296
|
<DocsProvider spec={spec} language={language ?? 'node'}>
|
|
297
297
|
<ComponentProvider components={componentOverrides}>
|
|
298
|
-
<NavigationProvider basePath={
|
|
298
|
+
<NavigationProvider basePath={RESOLVED_API_REFERENCE_PATH}>
|
|
299
299
|
<MarkdownProvider render={renderMarkdown} highlight={highlight}>
|
|
300
300
|
<div className={style.Overview}>
|
|
301
301
|
{resources
|
|
@@ -351,7 +351,7 @@ export function RenderSpec({
|
|
|
351
351
|
}}
|
|
352
352
|
>
|
|
353
353
|
<ComponentProvider components={componentOverrides}>
|
|
354
|
-
<NavigationProvider basePath={
|
|
354
|
+
<NavigationProvider basePath={RESOLVED_API_REFERENCE_PATH} selectedPath={path}>
|
|
355
355
|
<MarkdownProvider render={renderMarkdown} highlight={highlight}>
|
|
356
356
|
{
|
|
357
357
|
<div className="stldocs-root stl-ui-not-prose">
|
|
@@ -359,7 +359,7 @@ export function RenderSpec({
|
|
|
359
359
|
<SDKBreadcrumbs
|
|
360
360
|
spec={spec as SDKJSON.Spec}
|
|
361
361
|
currentPath={currentPath}
|
|
362
|
-
basePath={
|
|
362
|
+
basePath={RESOLVED_API_REFERENCE_PATH}
|
|
363
363
|
config={BREADCRUMB_CONFIG}
|
|
364
364
|
/>
|
|
365
365
|
{ENABLE_CONTEXT_MENU && <AIDropdown />}
|
|
@@ -21,27 +21,30 @@ export function makePlaceholderItems(id: number) {
|
|
|
21
21
|
|
|
22
22
|
type StarlightConfig = Parameters<typeof starlight>[0];
|
|
23
23
|
|
|
24
|
-
type SidebarConfigEntry = Exclude<StarlightConfig['sidebar'], undefined>[number];
|
|
24
|
+
export type SidebarConfigEntry = Exclude<StarlightConfig['sidebar'], undefined>[number];
|
|
25
25
|
|
|
26
26
|
export function getAPIReferencePlaceholderItemFromSidebarConfig(
|
|
27
27
|
sidebar: SidebarConfigEntry[],
|
|
28
|
-
): SidebarConfigEntry
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
28
|
+
): SidebarConfigEntry[] {
|
|
29
|
+
const items: SidebarConfigEntry[] = [];
|
|
30
|
+
|
|
31
|
+
function recursiveGetPlaceholderItems(entries: SidebarConfigEntry[]) {
|
|
32
|
+
for (const item of entries) {
|
|
33
|
+
if (typeof item === 'string') {
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if ('attrs' in item && item.attrs?.about === INTERNAL_REFERENCE_ENTRY_MARKER) {
|
|
37
|
+
items.push(item);
|
|
38
|
+
}
|
|
39
|
+
if ('items' in item) {
|
|
40
|
+
recursiveGetPlaceholderItems(item.items);
|
|
37
41
|
}
|
|
38
|
-
}
|
|
39
|
-
if ('attrs' in item && item.attrs?.about === INTERNAL_REFERENCE_ENTRY_MARKER) {
|
|
40
|
-
return item;
|
|
41
42
|
}
|
|
42
43
|
}
|
|
43
44
|
|
|
44
|
-
|
|
45
|
+
recursiveGetPlaceholderItems(sidebar);
|
|
46
|
+
|
|
47
|
+
return items;
|
|
45
48
|
}
|
|
46
49
|
|
|
47
50
|
type SidebarEntry = StarlightRouteData['sidebar'][number];
|