@shoalrun/cli 0.1.0-beta.1 → 1.0.0
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 +17 -0
- package/CODE-REFERENCES.md +137 -0
- package/README.md +8 -5
- package/adapters/python/requirements.txt +1 -0
- package/adapters/python/shoalrun_reference.py +234 -0
- package/agent-docs/.well-known/shoalrun/navigation/project-updates-50f26fe22670.txt +4 -2
- package/agent-docs/SNAPSHOT.json +5 -5
- package/agent-docs/about.md +3 -3
- package/agent-docs/api-docs/code-reference-settings.md +160 -0
- package/agent-docs/api-docs/code-reference-settings.sections/catalog-settings.md +50 -0
- package/agent-docs/api-docs/code-reference-settings.sections/complete-reference-page.md +46 -0
- package/agent-docs/api-docs/code-reference-settings.sections/converter-snapshot.md +58 -0
- package/agent-docs/api-docs/code-reference-settings.sections/descriptions-type-links-and-source-links.md +40 -0
- package/agent-docs/api-docs/code-reference-settings.sections/html-markdown-and-agents.md +38 -0
- package/agent-docs/api-docs/code-reference-settings.sections/metadata-and-selection.md +38 -0
- package/agent-docs/api-docs/code-reference-settings.sections/publication-sources.md +54 -0
- package/agent-docs/api-docs/code-reference-settings.sections/python-adapter-limits.md +38 -0
- package/agent-docs/api-docs/code-reference-settings.sections/related-reading.md +32 -0
- package/agent-docs/api-docs/code-reference-settings.sections/symbol-fields.md +56 -0
- package/agent-docs/api-docs/code-references.md +143 -0
- package/agent-docs/author/agent-overview.md +2 -2
- package/agent-docs/changelog/code-api-references.md +44 -0
- package/agent-docs/changelog.md +9 -1
- package/agent-docs/cli.md +11 -1
- package/agent-docs/cli.sections/audit-a-project-and-api-sources.md +1 -1
- package/agent-docs/cli.sections/author-pages.md +1 -1
- package/agent-docs/cli.sections/build-and-serve.md +1 -1
- package/agent-docs/cli.sections/inspect-config-and-operations.md +1 -1
- package/agent-docs/cli.sections/npm-scripts-in-this-repository.md +1 -1
- package/agent-docs/cli.sections/related-reading.md +1 -1
- package/agent-docs/cli.sections/search-and-chat.md +1 -1
- package/agent-docs/cli.sections/start-a-project.md +1 -1
- package/agent-docs/cli.sections/validate-code-reference-snapshots.md +41 -0
- package/agent-docs/cli.sections/working-tree-authoring-tools.md +1 -1
- package/agent-docs/config/apis.md +5 -1
- package/agent-docs/config/examples.md +3 -3
- package/agent-docs/config/examples.sections/feature-showcase.md +3 -3
- package/agent-docs/config/examples.sections/minimal-site.md +2 -2
- package/agent-docs/config/examples.sections/multilingual-help-center.md +2 -2
- package/agent-docs/config/examples.sections/parcel-api-documentation.md +2 -2
- package/agent-docs/config/examples.sections/related-reading.md +2 -2
- package/agent-docs/config/examples.sections/shared-company-preset.md +2 -2
- package/agent-docs/config.md +2 -2
- package/agent-docs/configuration.md +2 -2
- package/agent-docs/configuration.sections/build-several-sites-from-shared-content.md +1 -1
- package/agent-docs/configuration.sections/change-inherited-lists-deliberately.md +1 -1
- package/agent-docs/configuration.sections/extract-a-section-with-include.md +1 -1
- package/agent-docs/configuration.sections/inspect-and-validate-changes.md +1 -1
- package/agent-docs/configuration.sections/related-reading.md +1 -1
- package/agent-docs/configuration.sections/separate-config-inheritance-from-page-metadata.md +1 -1
- package/agent-docs/configuration.sections/share-defaults-through-extends.md +1 -1
- package/agent-docs/configuration.sections/start-with-one-working-file.md +2 -2
- package/agent-docs/configuration.sections/understand-the-three-stages.md +1 -1
- package/agent-docs/configuration.sections/understand-where-paths-point.md +1 -1
- package/agent-docs/documents.json +609 -215
- package/agent-docs/features.md +3 -2
- package/agent-docs/provenance.json +6 -6
- package/agent-docs/publish/api-references.md +3 -1
- package/agent-docs/publish/api-references.sections/author-the-reference-page.md +3 -1
- package/agent-docs/publish/api-references.sections/build-and-verify-the-output.md +3 -1
- package/agent-docs/publish/api-references.sections/inspect-the-machine-readable-contract.md +3 -1
- package/agent-docs/publish/api-references.sections/next-steps.md +3 -1
- package/agent-docs/publish/api-references.sections/preview-a-small-api-reference.md +3 -1
- package/agent-docs/publish/api-references.sections/put-the-spec-in-your-project.md +3 -1
- package/agent-docs/publish/api-references.sections/register-the-operation.md +3 -1
- package/agent-docs/publish/api-references.sections/related-reading.md +3 -1
- package/agent-docs/publish/api-references.sections/review-imported-content-before-publishing.md +3 -1
- package/agent-docs/publish/api-references.sections/what-readers-get.md +3 -1
- package/agent-docs/search-index.json +1 -1
- package/agent-docs/start.md +3 -3
- package/agent-docs/start.sections/add-the-page-to-navigation.md +2 -2
- package/agent-docs/start.sections/build-and-check-both-outputs.md +2 -2
- package/agent-docs/start.sections/build-this-site.md +2 -2
- package/agent-docs/start.sections/check-writing-style.md +2 -2
- package/agent-docs/start.sections/create-a-page.md +2 -2
- package/agent-docs/start.sections/make-it-yours.md +2 -2
- package/agent-docs/start.sections/migrating-from-github-packages.md +2 -2
- package/agent-docs/start.sections/prerequisites.md +2 -2
- package/agent-docs/start.sections/related-reading.md +2 -2
- package/agent-docs/start.sections/start-your-own-project.md +3 -3
- package/agent-docs/status.md +6 -4
- package/agent-docs/styling/themes.md +7 -3
- package/agent-docs/what-is-shoalrun.md +2 -2
- package/dist/artifact-bundle.d.ts +1 -0
- package/dist/artifact-bundle.js +11 -3
- package/dist/cli-discovery.d.ts +1 -1
- package/dist/cli-discovery.js +1 -0
- package/dist/cli.js +7 -0
- package/dist/code-reference-model.d.ts +85 -0
- package/dist/code-reference-model.js +73 -0
- package/dist/code-references.d.ts +23 -0
- package/dist/code-references.js +371 -0
- package/dist/compiler-config.d.ts +1 -0
- package/dist/compiler.js +4 -3
- package/dist/config.js +1 -1
- package/dist/content-source.d.ts +1 -0
- package/dist/content-workspace.d.ts +1 -0
- package/dist/content-workspace.js +2 -0
- package/dist/fonts.d.ts +9 -0
- package/dist/fonts.js +58 -3
- package/dist/page-materialization.js +3 -2
- package/dist/page-renderer.d.ts +1 -0
- package/dist/page-renderer.js +3 -1
- package/dist/publication-render.d.ts +2 -1
- package/dist/publication-render.js +2 -2
- package/dist/representation-tree.js +4 -0
- package/examples/code-references/content/start.md +53 -0
- package/examples/code-references/docs.config.yaml +262 -0
- package/examples/code-references/python/orchard/__init__.py +11 -0
- package/examples/code-references/python/orchard/client.py +212 -0
- package/examples/code-references/python/orchard/errors.py +31 -0
- package/examples/code-references/python/orchard/models.py +69 -0
- package/examples/code-references/python/orchard/pagination.py +39 -0
- package/examples/code-references/reference.json +1244 -0
- package/package.json +8 -1
- package/schemas/code-reference.schema.json +306 -0
- package/skills/shoalrun-author/SKILL.md +4 -0
- package/skills/shoalrun-author/references/code-api-references.md +15 -0
- package/styles/site.css +61 -2
package/dist/page-renderer.js
CHANGED
|
@@ -38,6 +38,8 @@ export function shareCardText(doc, config) {
|
|
|
38
38
|
return { title, summary: String(summary), type: typeLabel(doc.frontmatter.type) };
|
|
39
39
|
}
|
|
40
40
|
export function typeLabel(type) {
|
|
41
|
+
if (type === 'code-reference')
|
|
42
|
+
return 'Code API reference';
|
|
41
43
|
const words = String(type).split('-').filter(Boolean).map(word => word === 'api' ? 'API' : word);
|
|
42
44
|
const label = words.join(' ');
|
|
43
45
|
return label.charAt(0).toUpperCase() + label.slice(1);
|
|
@@ -192,6 +194,6 @@ export function buildHtmlPage(doc, tree, markdownUrl, siteTitle, navigation, exa
|
|
|
192
194
|
const menu = side || sectionNavigation ? `<a class="mobile-menu" href="#${side ? 'docs-navigation' : 'docs-sections'}">Menu</a>` : '';
|
|
193
195
|
const rail = toc || panel ? `<aside class="page-rail">${doc.endpoint ? `${panel}${toc}` : `${toc}${panel}`}</aside>` : '';
|
|
194
196
|
const breadcrumbs = (shell.breadcrumbs?.length ?? 0) > 1 && !hero ? `<nav class="doc-breadcrumbs" aria-label="Breadcrumb"><ol>${shell.breadcrumbs.map((item, index) => `<li>${index === shell.breadcrumbs.length - 1 ? `<span aria-current="page">${esc(item.label)}</span>` : item.url ? `<a href="${esc(item.url)}">${esc(item.label)}</a>` : `<span>${esc(item.label)}</span>`}</li>`).join('')}</ol></nav>` : '';
|
|
195
|
-
const markup = `<!doctype html><html lang="${esc(doc.variant.language)}"${shell.themeCss || shell.paletteCss ? ` data-theme="${esc(shell.preset ?? 'shoal')}" data-palette="${esc(shell.palette ?? '')}"` : ''}${shell.masthead ? ` data-masthead="${esc(shell.masthead)}"` : ''}${layout === 'docs' ? '' : ` data-layout="${layout}"`}><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="color-scheme" content="${shell.mode === 'system' ? 'light dark' : shell.mode ?? 'light'}">${shell.indexing === false || doc.frontmatter.seo?.noindex === true ? '<meta name="robots" content="noindex">' : ''}${shell.origin ? `<link rel="canonical" href="${esc(absolute(doc.route))}">` : ''}${shell.toggle ? '<script src="/assets/mode.js"></script>' : ''}<title>${esc(String(title))}</title>${description ? `<meta name="description" content="${esc(String(description))}">` : ''}${socialDescription ? `<meta property="og:description" content="${esc(socialDescription)}">` : ''}${social}<link rel="alternate" type="text/markdown" href="${esc(markdownUrl)}"><link rel="describedby" href="/llms.min.txt" title="Documentation index">${icons}${shell.preloadFont ? `<link rel="preload" href="/assets/fonts/${esc(shell.preloadFont)}" as="font" type="font/woff2" crossorigin>` : ''}<link rel="stylesheet" href="/assets/site.css">${article.includes('data-theme-preview') ? '<link rel="stylesheet" href="/assets/theme-preview.css">' : ''}${shell.themeCss ? '<link rel="stylesheet" href="/assets/theme.css" data-theme-link="theme">' : ''}${shell.paletteCss ? '<link rel="stylesheet" href="/assets/palette.css" data-theme-link="palette">' : ''}${shell.badgesCss ? '<link rel="stylesheet" href="/assets/badges.css">' : ''}${shell.themeSwitcher ? `<script src="/assets/theme-switcher.js" data-themes="${esc(shell.themeSwitcher)}"></script>` : ''}${shell.fontsCss ? '<link rel="stylesheet" href="/assets/fonts.css">' : ''}${customCss ? '<link rel="stylesheet" href="/assets/project.css">' : ''}</head><body><a class="skip" href="#main">Skip to content</a>${agent.mode === 'disclosure' ? '' : agentBlock}<header class="mast"><div class="mast-inner">${shell.home ? `<a class="${brandClass}" href="/">${brand}</a>` : `<span class="${brandClass}">${brand}</span>`}${publicationPicker(shell, esc)}${editionLabel && !shell.publicationChoices?.length && (shell.publicationAlternates?.length ?? 0) < 2 ? `<span class="edition">${esc(editionLabel)}</span>` : ''}${menu}${headerTools(shell, doc.variant, esc, readerConfig)}${agent.mode === 'disclosure' ? agentBlock : ''}</div></header>${sectionNavigation}${shortcuts}<div class="layout${layout === 'docs' ? '' : ` layout-${layout}`}${rail ? ' has-rail' : ''}${panel ? ' has-examples' : ''}${doc.endpoint ? ' api-reference' : ''}"><main id="main" class="content" tabindex="-1" data-document-type="${esc(doc.frontmatter.type)}"${readerConfig ? ` data-reader-page="${esc(readerFilterAttribute(doc.readerFilters ?? {}))}"` : ''}>${breadcrumbs}${hero ? '' : `<header class="page-head"><span class="eyebrow">${esc(typeLabel(doc.frontmatter.type))}</span>${doc.endpoint ? '' : badge(doc.frontmatter.subjectLifecycle)}<h1>${esc(doc.frontmatter.title)}${doc.endpoint ? badge(doc.frontmatter.subjectLifecycle) : ''}</h1>${pageHeader && !routeSummary ? `<p class="summary">${esc(pageHeader)}</p>` : ''}${pageDates}${endpoint}${audienceBadges}</header>`}${hero ? (pdfLink ? `<div class="page-formats">${pdfLink}</div>` : '') : `<div class="page-formats">${pdfAction?.placement === 'before' ? pdfLink : ''}<a class="formats" data-markdown-link href="${esc(markdownUrl)}">Read as Markdown</a><button type="button" class="formats" data-copy-markdown hidden>Copy as Markdown</button><span role="status" data-copy-markdown-status></span>${pdfAction?.placement === 'after' ? pdfLink : ''}</div>`}${toc ? '<div class="mobile-outline-slot"></div>' : ''}${jumps}${readerBanner}<article>${article}</article></main>${rail}${side}</div>${footer}${analyticsBootstrap}${readerBootstrap}${pdfAction?.mode === 'print' ? '<script type="module" src="/assets/print.js"></script>' : ''}<script type="module" src="/assets/copy-markdown.js"></script><script type="module" src="/assets/navigation.js"></script><script type="module" src="/assets/reader.js"></script><script type="module" src="/assets/tabs.js"></script>${shell.search ? '<script type="module" src="/assets/search.js"></script>' : ''}${article.includes('data-tooltip') ? '<script type="module" src="/assets/tooltips.js"></script>' : ''}${article.includes('data-component-module') ? '<script type="module" src="/assets/components.js"></script>' : ''}${article.includes('data-file-tree') ? '<script type="module" src="/assets/file-tree.js"></script>' : ''}${article.includes('data-image-expand') ? '<script type="module" src="/assets/image-viewer.js"></script>' : ''}${article.includes('data-table-filter') || article.includes('data-definition-filter') ? '<script type="module" src="/assets/table-filter.js"></script>' : ''}${article.includes('data-walkthrough') ? '<script type="module" src="/assets/walkthrough.js"></script>' : ''}${article.includes('data-cookbook-chooser') ? '<script type="module" src="/assets/cookbook-chooser.js"></script>' : ''}${article.includes('data-theme-preview') ? '<script type="module" src="/assets/theme-preview.js"></script>' : ''}${panel ? '<script type="module" src="/assets/example-panel.js"></script>' : ''}${panel.includes('data-code-samples') ? '<script type="module" src="/assets/code-samples.js"></script>' : ''}</body></html>`;
|
|
197
|
+
const markup = `<!doctype html><html lang="${esc(doc.variant.language)}"${shell.themeCss || shell.paletteCss ? ` data-theme="${esc(shell.preset ?? 'shoal')}" data-palette="${esc(shell.palette ?? '')}"` : ''}${shell.masthead ? ` data-masthead="${esc(shell.masthead)}"` : ''}${layout === 'docs' ? '' : ` data-layout="${layout}"`}><head><meta charset="utf-8"><meta name="viewport" content="width=device-width, initial-scale=1"><meta name="color-scheme" content="${shell.mode === 'system' ? 'light dark' : shell.mode ?? 'light'}">${shell.indexing === false || doc.frontmatter.seo?.noindex === true ? '<meta name="robots" content="noindex">' : ''}${shell.origin ? `<link rel="canonical" href="${esc(absolute(doc.route))}">` : ''}${shell.toggle ? '<script src="/assets/mode.js"></script>' : ''}<title>${esc(String(title))}</title>${description ? `<meta name="description" content="${esc(String(description))}">` : ''}${socialDescription ? `<meta property="og:description" content="${esc(socialDescription)}">` : ''}${social}<link rel="alternate" type="text/markdown" href="${esc(markdownUrl)}"><link rel="describedby" href="/llms.min.txt" title="Documentation index">${icons}${shell.preloadFont ? `<link rel="preload" href="/assets/fonts/${esc(shell.preloadFont)}" as="font" type="font/woff2" crossorigin>` : ''}${(shell.preloadFonts ?? []).map(font => `<link rel="preload" href="${esc(font.href)}" as="font" type="${esc(font.type)}" crossorigin>`).join('')}<link rel="stylesheet" href="/assets/site.css">${article.includes('data-theme-preview') ? '<link rel="stylesheet" href="/assets/theme-preview.css">' : ''}${shell.themeCss ? '<link rel="stylesheet" href="/assets/theme.css" data-theme-link="theme">' : ''}${shell.paletteCss ? '<link rel="stylesheet" href="/assets/palette.css" data-theme-link="palette">' : ''}${shell.badgesCss ? '<link rel="stylesheet" href="/assets/badges.css">' : ''}${shell.themeSwitcher ? `<script src="/assets/theme-switcher.js" data-themes="${esc(shell.themeSwitcher)}"></script>` : ''}${shell.fontsCss ? '<link rel="stylesheet" href="/assets/fonts.css">' : ''}${customCss ? '<link rel="stylesheet" href="/assets/project.css">' : ''}</head><body><a class="skip" href="#main">Skip to content</a>${agent.mode === 'disclosure' ? '' : agentBlock}<header class="mast"><div class="mast-inner">${shell.home ? `<a class="${brandClass}" href="/">${brand}</a>` : `<span class="${brandClass}">${brand}</span>`}${publicationPicker(shell, esc)}${editionLabel && !shell.publicationChoices?.length && (shell.publicationAlternates?.length ?? 0) < 2 ? `<span class="edition">${esc(editionLabel)}</span>` : ''}${menu}${headerTools(shell, doc.variant, esc, readerConfig)}${agent.mode === 'disclosure' ? agentBlock : ''}</div></header>${sectionNavigation}${shortcuts}<div class="layout${layout === 'docs' ? '' : ` layout-${layout}`}${rail ? ' has-rail' : ''}${panel ? ' has-examples' : ''}${doc.endpoint ? ' api-reference' : ''}"><main id="main" class="content" tabindex="-1" data-document-type="${esc(doc.frontmatter.type)}"${readerConfig ? ` data-reader-page="${esc(readerFilterAttribute(doc.readerFilters ?? {}))}"` : ''}>${breadcrumbs}${hero ? '' : `<header class="page-head"><span class="eyebrow">${esc(typeLabel(doc.frontmatter.type))}</span>${doc.endpoint ? '' : badge(doc.frontmatter.subjectLifecycle)}<h1>${esc(doc.frontmatter.title)}${doc.endpoint ? badge(doc.frontmatter.subjectLifecycle) : ''}</h1>${pageHeader && !routeSummary ? `<p class="summary">${esc(pageHeader)}</p>` : ''}${pageDates}${endpoint}${audienceBadges}</header>`}${hero ? (pdfLink ? `<div class="page-formats">${pdfLink}</div>` : '') : `<div class="page-formats">${pdfAction?.placement === 'before' ? pdfLink : ''}<a class="formats" data-markdown-link href="${esc(markdownUrl)}">Read as Markdown</a><button type="button" class="formats" data-copy-markdown hidden>Copy as Markdown</button><span role="status" data-copy-markdown-status></span>${pdfAction?.placement === 'after' ? pdfLink : ''}</div>`}${toc ? '<div class="mobile-outline-slot"></div>' : ''}${jumps}${readerBanner}<article>${article}</article></main>${rail}${side}</div>${footer}${analyticsBootstrap}${readerBootstrap}${pdfAction?.mode === 'print' ? '<script type="module" src="/assets/print.js"></script>' : ''}<script type="module" src="/assets/copy-markdown.js"></script><script type="module" src="/assets/navigation.js"></script><script type="module" src="/assets/reader.js"></script><script type="module" src="/assets/tabs.js"></script>${shell.search ? '<script type="module" src="/assets/search.js"></script>' : ''}${article.includes('data-tooltip') ? '<script type="module" src="/assets/tooltips.js"></script>' : ''}${article.includes('data-component-module') ? '<script type="module" src="/assets/components.js"></script>' : ''}${article.includes('data-file-tree') ? '<script type="module" src="/assets/file-tree.js"></script>' : ''}${article.includes('data-image-expand') ? '<script type="module" src="/assets/image-viewer.js"></script>' : ''}${article.includes('data-table-filter') || article.includes('data-definition-filter') ? '<script type="module" src="/assets/table-filter.js"></script>' : ''}${article.includes('data-walkthrough') ? '<script type="module" src="/assets/walkthrough.js"></script>' : ''}${article.includes('data-cookbook-chooser') ? '<script type="module" src="/assets/cookbook-chooser.js"></script>' : ''}${article.includes('data-theme-preview') ? '<script type="module" src="/assets/theme-preview.js"></script>' : ''}${panel ? '<script type="module" src="/assets/example-panel.js"></script>' : ''}${panel.includes('data-code-samples') ? '<script type="module" src="/assets/code-samples.js"></script>' : ''}</body></html>`;
|
|
196
198
|
return basePath ? markup.replace(/((?:href|src)=")\/(assets\/|llms(?:\.min)?\.txt|apple-touch-icon\.png)/g, `$1${basePath}/$2`).replace('href="/"', `href="${basePath}/"`) : markup;
|
|
197
199
|
}
|
|
@@ -8,7 +8,7 @@ import type { ReaderFiltersConfig } from './reader-filters.js';
|
|
|
8
8
|
import type { CodeHighlighter } from './highlight.js';
|
|
9
9
|
import type { MaterializedPage } from './page-materialization.js';
|
|
10
10
|
import type { ResolvedCompilerConfig, CompilerSiteConfig, CompilerPublicationsConfig } from './compiler-config.js';
|
|
11
|
-
export declare function renderPublicationPages({ rendered, docs, relationships, knownOperations, cardUses, publishedRelationships, cookbooks, documentRoutes, basePath, siteOrigin, colorMode, config, highlighter, editionLabel, customStyleFile, themePreset, palette, themeStyleFile, generatedPaletteCss, generatedBadgeCss, themeSwitcherData, generatedFontsCss, fontsPreload, shareFor, faviconRoute, logoRoute, modeToggle, header, footer, search, readerFilters, variants, externalDocuments, externalSiteLinks, navigationSpec, navigationEntries, navigationTagOrder, freshness }: {
|
|
11
|
+
export declare function renderPublicationPages({ rendered, docs, relationships, knownOperations, cardUses, publishedRelationships, cookbooks, documentRoutes, basePath, siteOrigin, colorMode, config, highlighter, editionLabel, customStyleFile, themePreset, palette, themeStyleFile, generatedPaletteCss, generatedBadgeCss, themeSwitcherData, generatedFontsCss, fontsPreload, customFontPreloads, shareFor, faviconRoute, logoRoute, modeToggle, header, footer, search, readerFilters, variants, externalDocuments, externalSiteLinks, navigationSpec, navigationEntries, navigationTagOrder, freshness }: {
|
|
12
12
|
freshness?: Freshness;
|
|
13
13
|
rendered: MaterializedPage[];
|
|
14
14
|
docs: Map<string, Document>;
|
|
@@ -41,6 +41,7 @@ export declare function renderPublicationPages({ rendered, docs, relationships,
|
|
|
41
41
|
themeSwitcherData?: string;
|
|
42
42
|
generatedFontsCss?: string;
|
|
43
43
|
fontsPreload?: string;
|
|
44
|
+
customFontPreloads?: import('./fonts.js').FontPreload[];
|
|
44
45
|
shareFor: (doc: Document) => {
|
|
45
46
|
route: string;
|
|
46
47
|
generated: boolean;
|
|
@@ -12,7 +12,7 @@ import { navigationPath, navigationTab, navigationTabRecord, resolveProjectNavig
|
|
|
12
12
|
import { outputUrl, publicTree, resolveOutputLinks } from './representation-tree.js';
|
|
13
13
|
import { presetCatalog } from './palettes.js';
|
|
14
14
|
const keyFor = documentKey;
|
|
15
|
-
export function renderPublicationPages({ rendered, docs, relationships, knownOperations, cardUses, publishedRelationships, cookbooks, documentRoutes, basePath, siteOrigin, colorMode, config, highlighter, editionLabel, customStyleFile, themePreset, palette, themeStyleFile, generatedPaletteCss, generatedBadgeCss, themeSwitcherData, generatedFontsCss, fontsPreload, shareFor, faviconRoute, logoRoute, modeToggle, header, footer, search, readerFilters, variants, externalDocuments, externalSiteLinks, navigationSpec, navigationEntries, navigationTagOrder, freshness }) {
|
|
15
|
+
export function renderPublicationPages({ rendered, docs, relationships, knownOperations, cardUses, publishedRelationships, cookbooks, documentRoutes, basePath, siteOrigin, colorMode, config, highlighter, editionLabel, customStyleFile, themePreset, palette, themeStyleFile, generatedPaletteCss, generatedBadgeCss, themeSwitcherData, generatedFontsCss, fontsPreload, customFontPreloads, shareFor, faviconRoute, logoRoute, modeToggle, header, footer, search, readerFilters, variants, externalDocuments, externalSiteLinks, navigationSpec, navigationEntries, navigationTagOrder, freshness }) {
|
|
16
16
|
const resolvedNavigation = new Map();
|
|
17
17
|
const selector = config.site.publicationSelector;
|
|
18
18
|
if (selector !== undefined && (!isConfigMapping(selector) || Object.keys(selector).some(key => key !== 'showLanguage') || (selector.showLanguage !== undefined && typeof selector.showLanguage !== 'boolean')))
|
|
@@ -102,7 +102,7 @@ export function renderPublicationPages({ rendered, docs, relationships, knownOpe
|
|
|
102
102
|
const group = variant.product === undefined ? config.site.title : config.publications.products?.[variant.product]?.label ?? variant.product;
|
|
103
103
|
return [{ group, label: `${group} · ${variant.channel} · ${variant.version}${showLanguage ? ` · ${variant.language}` : ''}`, url: target.route, current: samePublication(page.doc.variant, variant) }];
|
|
104
104
|
}) : [];
|
|
105
|
-
page.html = buildHtmlPage(page.doc, page.htmlTree, page.doc.markdownRoute, config.site.title, navigation, page.pageExamples, page.pageShapes, highlighter, editionLabel(page.doc.variant), !!customStyleFile, { preset: themePreset, palette: palette.name, themeCss: !!themeStyleFile, paletteCss: !!generatedPaletteCss, badgesCss: !!generatedBadgeCss, themeSwitcher: themeSwitcherData, fontsCss: !!generatedFontsCss, preloadFont: fontsPreload, masthead: presetCatalog.find(preset => preset.name === themePreset)?.masthead, share: shareFor(page.doc), favicon: faviconRoute, logo: logoRoute, touchIcon: !faviconRoute.endsWith('.png'), origin: siteOrigin, indexing: config.site.indexing !== false, home: hasHome, mode: colorMode, toggle: modeToggle, header, footer, search: search.provider !== 'none', publicationChoices, publicationAlternates, breadcrumbs }, page.pageCurl, page.pageSamples, { ...config, readerFilters });
|
|
105
|
+
page.html = buildHtmlPage(page.doc, page.htmlTree, page.doc.markdownRoute, config.site.title, navigation, page.pageExamples, page.pageShapes, highlighter, editionLabel(page.doc.variant), !!customStyleFile, { preset: themePreset, palette: palette.name, themeCss: !!themeStyleFile, paletteCss: !!generatedPaletteCss, badgesCss: !!generatedBadgeCss, themeSwitcher: themeSwitcherData, fontsCss: !!generatedFontsCss, preloadFont: fontsPreload, preloadFonts: customFontPreloads, masthead: presetCatalog.find(preset => preset.name === themePreset)?.masthead, share: shareFor(page.doc), favicon: faviconRoute, logo: logoRoute, touchIcon: !faviconRoute.endsWith('.png'), origin: siteOrigin, indexing: config.site.indexing !== false, home: hasHome, mode: colorMode, toggle: modeToggle, header, footer, search: search.provider !== 'none', publicationChoices, publicationAlternates, breadcrumbs }, page.pageCurl, page.pageSamples, { ...config, readerFilters });
|
|
106
106
|
}
|
|
107
107
|
return resolvedNavigation;
|
|
108
108
|
}
|
|
@@ -66,6 +66,10 @@ export function publicTree(tree, representation, documentRoutes, mode = 'light',
|
|
|
66
66
|
if (node.type === 'docReaderFilter') {
|
|
67
67
|
return representation === 'markdown' ? [] : [element('div', { className: ['reader-filter-slot'], 'data-reader-filter': JSON.stringify(node.control) }, [])];
|
|
68
68
|
}
|
|
69
|
+
if (node.type === 'table' && node.data?.referenceTableLabel && representation === 'html') {
|
|
70
|
+
const table = { ...node, children: node.children.flatMap(walk) };
|
|
71
|
+
return [element('div', { className: ['code-reference-table-scroll'], role: 'region', 'aria-label': node.data.referenceTableLabel, tabIndex: 0 }, [table])];
|
|
72
|
+
}
|
|
69
73
|
if (node.type === 'docTable') {
|
|
70
74
|
const table = node.children.flatMap(walk);
|
|
71
75
|
if (representation === 'markdown')
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: guide.start
|
|
3
|
+
title: Python SDK
|
|
4
|
+
summary: Explore a typed SDK with synchronous and async clients, models, pagination, and exceptions.
|
|
5
|
+
type: guide
|
|
6
|
+
slug: /
|
|
7
|
+
channel: production
|
|
8
|
+
version: current
|
|
9
|
+
language: en
|
|
10
|
+
access: { policy: public }
|
|
11
|
+
---
|
|
12
|
+
This example SDK manages records. Its reference pages are generated from Python source and docstrings, then rendered with Shoalrun's normal theme, navigation, search, and Markdown output.
|
|
13
|
+
|
|
14
|
+
The sample client stores records in memory. It doesn't connect to a live service.
|
|
15
|
+
|
|
16
|
+
## Fetch a typed record
|
|
17
|
+
|
|
18
|
+
```python
|
|
19
|
+
from orchard import Client
|
|
20
|
+
|
|
21
|
+
client = Client("demo-key")
|
|
22
|
+
record = client.fetch("rec_42")
|
|
23
|
+
print(record.title)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Read [Client](doc:reference.client) for configuration and [fetch](doc:reference.fetch) for its typed and raw-response overloads.
|
|
27
|
+
|
|
28
|
+
## Work with more than one page
|
|
29
|
+
|
|
30
|
+
```python
|
|
31
|
+
from orchard import RecordStatus
|
|
32
|
+
|
|
33
|
+
for record in client.iter_records(page_size=50, status=RecordStatus.READY):
|
|
34
|
+
print(record.id, record.title)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
Choose [list_records](doc:reference.Client.list_records) when your application needs explicit cursor control, or [Page.map](doc:reference.pagination.Page.map) to transform a response without losing its pagination metadata.
|
|
38
|
+
|
|
39
|
+
## Use an async client
|
|
40
|
+
|
|
41
|
+
```python
|
|
42
|
+
from orchard import AsyncClient
|
|
43
|
+
|
|
44
|
+
client = AsyncClient("demo-key")
|
|
45
|
+
async for record in client.iter_records(page_size=50):
|
|
46
|
+
print(record.title)
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Browse [AsyncClient](doc:reference.AsyncClient), [Record](doc:reference.models.Record), and the [typed exceptions](doc:reference.errors) to see how the generated reference fits together.
|
|
50
|
+
|
|
51
|
+
## Choose how to browse
|
|
52
|
+
|
|
53
|
+
Read the [Client class with member details inline](doc:reference.client), or open the [complete Python SDK reference](doc:reference.complete) to browse everything on one page. The example uses `layout: classes` and enables `singlePage` in its catalog configuration. Individual symbol links remain available.
|
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
schemaVersion: 1
|
|
2
|
+
site:
|
|
3
|
+
title: Python SDK documentation
|
|
4
|
+
publications:
|
|
5
|
+
channels:
|
|
6
|
+
production: {}
|
|
7
|
+
versions:
|
|
8
|
+
current: {}
|
|
9
|
+
defaults:
|
|
10
|
+
channel: production
|
|
11
|
+
version: current
|
|
12
|
+
language: en
|
|
13
|
+
enabled:
|
|
14
|
+
- channel: production
|
|
15
|
+
version: current
|
|
16
|
+
language: en
|
|
17
|
+
codeReferences:
|
|
18
|
+
sdk:
|
|
19
|
+
source:
|
|
20
|
+
kind: file
|
|
21
|
+
path: ./reference.json
|
|
22
|
+
symbols:
|
|
23
|
+
orchard:
|
|
24
|
+
documentId: reference.orchard
|
|
25
|
+
slug: /reference/orchard
|
|
26
|
+
orchard.client:
|
|
27
|
+
documentId: reference.clients
|
|
28
|
+
slug: /reference/clients
|
|
29
|
+
orchard.client.AsyncClient:
|
|
30
|
+
documentId: reference.AsyncClient
|
|
31
|
+
slug: /reference/async-client
|
|
32
|
+
orchard.client.AsyncClient.__init__:
|
|
33
|
+
documentId: reference.AsyncClient.__init__
|
|
34
|
+
slug: /reference/async-client/constructor
|
|
35
|
+
orchard.client.AsyncClient.fetch:
|
|
36
|
+
documentId: reference.AsyncClient.fetch
|
|
37
|
+
slug: /reference/async-client/fetch
|
|
38
|
+
orchard.client.AsyncClient.iter_records:
|
|
39
|
+
documentId: reference.AsyncClient.iter_records
|
|
40
|
+
slug: /reference/async-client/iter-records
|
|
41
|
+
orchard.client.Client:
|
|
42
|
+
documentId: reference.client
|
|
43
|
+
slug: /reference/client
|
|
44
|
+
orchard.client.Client.__init__:
|
|
45
|
+
documentId: reference.Client.__init__
|
|
46
|
+
slug: /reference/client/constructor
|
|
47
|
+
orchard.client.Client.base_url:
|
|
48
|
+
documentId: reference.Client.base_url
|
|
49
|
+
slug: /reference/client/base-url
|
|
50
|
+
orchard.client.Client.bulk_create:
|
|
51
|
+
documentId: reference.Client.bulk_create
|
|
52
|
+
slug: /reference/client/bulk-create
|
|
53
|
+
orchard.client.Client.create_record:
|
|
54
|
+
documentId: reference.Client.create_record
|
|
55
|
+
slug: /reference/client/create-record
|
|
56
|
+
orchard.client.Client.fetch:
|
|
57
|
+
documentId: reference.fetch
|
|
58
|
+
slug: /reference/client/fetch
|
|
59
|
+
orchard.client.Client.iter_records:
|
|
60
|
+
documentId: reference.Client.iter_records
|
|
61
|
+
slug: /reference/client/iter-records
|
|
62
|
+
orchard.client.Client.list_records:
|
|
63
|
+
documentId: reference.Client.list_records
|
|
64
|
+
slug: /reference/client/list-records
|
|
65
|
+
orchard.client.Client.max_retries:
|
|
66
|
+
documentId: reference.Client.max_retries
|
|
67
|
+
slug: /reference/client/max-retries
|
|
68
|
+
orchard.client.Client.timeout:
|
|
69
|
+
documentId: reference.Client.timeout
|
|
70
|
+
slug: /reference/client/timeout
|
|
71
|
+
orchard.errors:
|
|
72
|
+
documentId: reference.errors
|
|
73
|
+
slug: /reference/errors
|
|
74
|
+
orchard.errors.APIError:
|
|
75
|
+
documentId: reference.errors.APIError
|
|
76
|
+
slug: /reference/errors/apierror
|
|
77
|
+
orchard.errors.APIError.__init__:
|
|
78
|
+
documentId: reference.errors.APIError.__init__
|
|
79
|
+
slug: /reference/errors/apierror/constructor
|
|
80
|
+
orchard.errors.APIError.request_id:
|
|
81
|
+
documentId: reference.errors.APIError.request_id
|
|
82
|
+
slug: /reference/errors/apierror/request-id
|
|
83
|
+
orchard.errors.AuthenticationError:
|
|
84
|
+
documentId: reference.errors.AuthenticationError
|
|
85
|
+
slug: /reference/errors/authenticationerror
|
|
86
|
+
orchard.errors.NotFoundError:
|
|
87
|
+
documentId: reference.errors.NotFoundError
|
|
88
|
+
slug: /reference/errors/notfounderror
|
|
89
|
+
orchard.errors.RateLimitError:
|
|
90
|
+
documentId: reference.errors.RateLimitError
|
|
91
|
+
slug: /reference/errors/ratelimiterror
|
|
92
|
+
orchard.errors.RateLimitError.__init__:
|
|
93
|
+
documentId: reference.errors.RateLimitError.__init__
|
|
94
|
+
slug: /reference/errors/ratelimiterror/constructor
|
|
95
|
+
orchard.errors.RateLimitError.retry_after:
|
|
96
|
+
documentId: reference.errors.RateLimitError.retry_after
|
|
97
|
+
slug: /reference/errors/ratelimiterror/retry-after
|
|
98
|
+
orchard.models:
|
|
99
|
+
documentId: reference.models
|
|
100
|
+
slug: /reference/models
|
|
101
|
+
orchard.models.Record:
|
|
102
|
+
documentId: reference.models.Record
|
|
103
|
+
slug: /reference/models/record
|
|
104
|
+
orchard.models.Record.created_at:
|
|
105
|
+
documentId: reference.models.Record.created_at
|
|
106
|
+
slug: /reference/models/record/created-at
|
|
107
|
+
orchard.models.Record.id:
|
|
108
|
+
documentId: reference.models.Record.id
|
|
109
|
+
slug: /reference/models/record/id
|
|
110
|
+
orchard.models.Record.labels:
|
|
111
|
+
documentId: reference.models.Record.labels
|
|
112
|
+
slug: /reference/models/record/labels
|
|
113
|
+
orchard.models.Record.status:
|
|
114
|
+
documentId: reference.models.Record.status
|
|
115
|
+
slug: /reference/models/record/status
|
|
116
|
+
orchard.models.Record.title:
|
|
117
|
+
documentId: reference.models.Record.title
|
|
118
|
+
slug: /reference/models/record/title
|
|
119
|
+
orchard.models.Record.to_dict:
|
|
120
|
+
documentId: reference.models.Record.to_dict
|
|
121
|
+
slug: /reference/models/record/to-dict
|
|
122
|
+
orchard.models.RecordDict:
|
|
123
|
+
documentId: reference.models.RecordDict
|
|
124
|
+
slug: /reference/models/recorddict
|
|
125
|
+
orchard.models.RecordDict.id:
|
|
126
|
+
documentId: reference.models.RecordDict.id
|
|
127
|
+
slug: /reference/models/recorddict/id
|
|
128
|
+
orchard.models.RecordDict.status:
|
|
129
|
+
documentId: reference.models.RecordDict.status
|
|
130
|
+
slug: /reference/models/recorddict/status
|
|
131
|
+
orchard.models.RecordDict.title:
|
|
132
|
+
documentId: reference.models.RecordDict.title
|
|
133
|
+
slug: /reference/models/recorddict/title
|
|
134
|
+
orchard.models.RecordInput:
|
|
135
|
+
documentId: reference.models.RecordInput
|
|
136
|
+
slug: /reference/models/recordinput
|
|
137
|
+
orchard.models.RecordInput.labels:
|
|
138
|
+
documentId: reference.models.RecordInput.labels
|
|
139
|
+
slug: /reference/models/recordinput/labels
|
|
140
|
+
orchard.models.RecordInput.title:
|
|
141
|
+
documentId: reference.models.RecordInput.title
|
|
142
|
+
slug: /reference/models/recordinput/title
|
|
143
|
+
orchard.models.RecordStatus:
|
|
144
|
+
documentId: reference.models.RecordStatus
|
|
145
|
+
slug: /reference/models/recordstatus
|
|
146
|
+
orchard.models.RecordStatus.FAILED:
|
|
147
|
+
documentId: reference.models.RecordStatus.FAILED
|
|
148
|
+
slug: /reference/models/recordstatus/failed
|
|
149
|
+
orchard.models.RecordStatus.PENDING:
|
|
150
|
+
documentId: reference.models.RecordStatus.PENDING
|
|
151
|
+
slug: /reference/models/recordstatus/pending
|
|
152
|
+
orchard.models.RecordStatus.READY:
|
|
153
|
+
documentId: reference.models.RecordStatus.READY
|
|
154
|
+
slug: /reference/models/recordstatus/ready
|
|
155
|
+
orchard.pagination:
|
|
156
|
+
documentId: reference.pagination
|
|
157
|
+
slug: /reference/pagination
|
|
158
|
+
orchard.pagination.Page:
|
|
159
|
+
documentId: reference.pagination.Page
|
|
160
|
+
slug: /reference/pagination/page
|
|
161
|
+
orchard.pagination.Page.has_more:
|
|
162
|
+
documentId: reference.pagination.Page.has_more
|
|
163
|
+
slug: /reference/pagination/page/has-more
|
|
164
|
+
orchard.pagination.Page.items:
|
|
165
|
+
documentId: reference.pagination.Page.items
|
|
166
|
+
slug: /reference/pagination/page/items
|
|
167
|
+
orchard.pagination.Page.map:
|
|
168
|
+
documentId: reference.pagination.Page.map
|
|
169
|
+
slug: /reference/pagination/page/map
|
|
170
|
+
orchard.pagination.Page.next_cursor:
|
|
171
|
+
documentId: reference.pagination.Page.next_cursor
|
|
172
|
+
slug: /reference/pagination/page/next-cursor
|
|
173
|
+
orchard.pagination.Page.total:
|
|
174
|
+
documentId: reference.pagination.Page.total
|
|
175
|
+
slug: /reference/pagination/page/total
|
|
176
|
+
orchard.pagination.T:
|
|
177
|
+
documentId: reference.pagination.T
|
|
178
|
+
slug: /reference/pagination/t
|
|
179
|
+
orchard.pagination.U:
|
|
180
|
+
documentId: reference.pagination.U
|
|
181
|
+
slug: /reference/pagination/u
|
|
182
|
+
layout: classes
|
|
183
|
+
singlePage:
|
|
184
|
+
documentId: reference.complete
|
|
185
|
+
slug: /reference/all
|
|
186
|
+
title: Complete Python SDK reference
|
|
187
|
+
summary: Browse every public module, class, method, and field on one page.
|
|
188
|
+
navigation:
|
|
189
|
+
- id: start
|
|
190
|
+
doc: guide.start
|
|
191
|
+
- id: complete
|
|
192
|
+
doc: reference.complete
|
|
193
|
+
- id: overview
|
|
194
|
+
label: Package
|
|
195
|
+
items:
|
|
196
|
+
- id: orchard
|
|
197
|
+
doc: reference.orchard
|
|
198
|
+
- id: orchard.client
|
|
199
|
+
doc: reference.clients
|
|
200
|
+
- id: client
|
|
201
|
+
label: Synchronous client
|
|
202
|
+
items:
|
|
203
|
+
- id: orchard.client.Client
|
|
204
|
+
doc: reference.client
|
|
205
|
+
- id: orchard.client.Client.__init__
|
|
206
|
+
doc: reference.Client.__init__
|
|
207
|
+
- id: orchard.client.Client.fetch
|
|
208
|
+
doc: reference.fetch
|
|
209
|
+
- id: orchard.client.Client.list_records
|
|
210
|
+
doc: reference.Client.list_records
|
|
211
|
+
- id: orchard.client.Client.iter_records
|
|
212
|
+
doc: reference.Client.iter_records
|
|
213
|
+
- id: orchard.client.Client.create_record
|
|
214
|
+
doc: reference.Client.create_record
|
|
215
|
+
- id: orchard.client.Client.bulk_create
|
|
216
|
+
doc: reference.Client.bulk_create
|
|
217
|
+
- id: async
|
|
218
|
+
label: Asynchronous client
|
|
219
|
+
items:
|
|
220
|
+
- id: orchard.client.AsyncClient
|
|
221
|
+
doc: reference.AsyncClient
|
|
222
|
+
- id: orchard.client.AsyncClient.fetch
|
|
223
|
+
doc: reference.AsyncClient.fetch
|
|
224
|
+
- id: orchard.client.AsyncClient.iter_records
|
|
225
|
+
doc: reference.AsyncClient.iter_records
|
|
226
|
+
- id: models
|
|
227
|
+
label: Models
|
|
228
|
+
items:
|
|
229
|
+
- id: orchard.models
|
|
230
|
+
doc: reference.models
|
|
231
|
+
- id: orchard.models.Record
|
|
232
|
+
doc: reference.models.Record
|
|
233
|
+
- id: orchard.models.RecordInput
|
|
234
|
+
doc: reference.models.RecordInput
|
|
235
|
+
- id: orchard.models.RecordDict
|
|
236
|
+
doc: reference.models.RecordDict
|
|
237
|
+
- id: orchard.models.RecordStatus
|
|
238
|
+
doc: reference.models.RecordStatus
|
|
239
|
+
- id: orchard.models.Record.to_dict
|
|
240
|
+
doc: reference.models.Record.to_dict
|
|
241
|
+
- id: pagination
|
|
242
|
+
label: Pagination
|
|
243
|
+
items:
|
|
244
|
+
- id: orchard.pagination.Page
|
|
245
|
+
doc: reference.pagination.Page
|
|
246
|
+
- id: orchard.pagination.Page.map
|
|
247
|
+
doc: reference.pagination.Page.map
|
|
248
|
+
- id: orchard.pagination.Page.has_more
|
|
249
|
+
doc: reference.pagination.Page.has_more
|
|
250
|
+
- id: errors
|
|
251
|
+
label: Exceptions
|
|
252
|
+
items:
|
|
253
|
+
- id: orchard.errors
|
|
254
|
+
doc: reference.errors
|
|
255
|
+
- id: orchard.errors.APIError
|
|
256
|
+
doc: reference.errors.APIError
|
|
257
|
+
- id: orchard.errors.AuthenticationError
|
|
258
|
+
doc: reference.errors.AuthenticationError
|
|
259
|
+
- id: orchard.errors.NotFoundError
|
|
260
|
+
doc: reference.errors.NotFoundError
|
|
261
|
+
- id: orchard.errors.RateLimitError
|
|
262
|
+
doc: reference.errors.RateLimitError
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"""A sample SDK for working with records, collections, and paginated results.
|
|
2
|
+
|
|
3
|
+
Use [Client](symbol:orchard.client.Client) in synchronous applications, or
|
|
4
|
+
[AsyncClient](symbol:orchard.client.AsyncClient) in an async service. Models,
|
|
5
|
+
pagination helpers, and typed exceptions have their own reference pages.
|
|
6
|
+
|
|
7
|
+
This package is documentation example code. It doesn't contact a live service.
|
|
8
|
+
"""
|
|
9
|
+
from .client import AsyncClient, Client
|
|
10
|
+
from .models import Record, RecordInput, RecordStatus
|
|
11
|
+
from .pagination import Page
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"""Synchronous and asynchronous clients for the sample records SDK."""
|
|
2
|
+
from collections.abc import AsyncIterator, Iterator, Sequence
|
|
3
|
+
from typing import Literal, overload
|
|
4
|
+
from .errors import AuthenticationError, NotFoundError
|
|
5
|
+
from .models import Record, RecordDict, RecordInput, RecordStatus
|
|
6
|
+
from .pagination import Page
|
|
7
|
+
|
|
8
|
+
class Client:
|
|
9
|
+
"""Manage records from a synchronous Python application.
|
|
10
|
+
|
|
11
|
+
Create one client per API credential and reuse it across requests. Use
|
|
12
|
+
[AsyncClient](symbol:orchard.client.AsyncClient) in an async application.
|
|
13
|
+
|
|
14
|
+
The sample client keeps records in memory; it doesn't make network calls.
|
|
15
|
+
"""
|
|
16
|
+
def __init__(self, api_key: str, *, base_url: str = "https://api.example.com/v1", timeout: float = 10.0, max_retries: int = 2):
|
|
17
|
+
"""Configure a reusable client.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
api_key: Credential used to identify the application.
|
|
21
|
+
base_url: Root URL of the API deployment.
|
|
22
|
+
timeout: Default request timeout, in seconds.
|
|
23
|
+
max_retries: Number of retries for transient failures.
|
|
24
|
+
|
|
25
|
+
Raises:
|
|
26
|
+
AuthenticationError: If the API key is empty.
|
|
27
|
+
"""
|
|
28
|
+
if not api_key:
|
|
29
|
+
raise AuthenticationError("API key must not be empty")
|
|
30
|
+
self.base_url = base_url
|
|
31
|
+
self.timeout = timeout
|
|
32
|
+
self.max_retries = max_retries
|
|
33
|
+
self._records: dict[str, Record] = {"rec_42": Record("rec_42", "Getting started")}
|
|
34
|
+
|
|
35
|
+
@overload
|
|
36
|
+
def fetch(self, record_id: str, *, raw: Literal[False] = False, timeout: float | None = None) -> Record: ...
|
|
37
|
+
@overload
|
|
38
|
+
def fetch(self, record_id: str, *, raw: Literal[True], timeout: float | None = None) -> RecordDict: ...
|
|
39
|
+
def fetch(self, record_id: str, *, raw: bool = False, timeout: float | None = None) -> Record | RecordDict:
|
|
40
|
+
"""Retrieve a record by its stable identifier.
|
|
41
|
+
|
|
42
|
+
The default response is a typed [Record](symbol:orchard.models.Record).
|
|
43
|
+
Set `raw=True` to receive a dictionary for serialization or a legacy
|
|
44
|
+
integration. An explicit timeout overrides the client's default.
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
record_id: Stable identifier of the record to retrieve.
|
|
48
|
+
raw: Return a wire-format dictionary instead of a model.
|
|
49
|
+
timeout: Request timeout override, in seconds.
|
|
50
|
+
|
|
51
|
+
Returns:
|
|
52
|
+
The record model, or a dictionary when `raw=True`.
|
|
53
|
+
|
|
54
|
+
Raises:
|
|
55
|
+
ValueError: If the record identifier is empty.
|
|
56
|
+
NotFoundError: If no record matches the identifier.
|
|
57
|
+
|
|
58
|
+
Examples:
|
|
59
|
+
>>> client = Client("demo-key")
|
|
60
|
+
>>> record = client.fetch("rec_42")
|
|
61
|
+
>>> record.title
|
|
62
|
+
'Getting started'
|
|
63
|
+
>>> payload = client.fetch("rec_42", raw=True)
|
|
64
|
+
>>> payload["status"]
|
|
65
|
+
'ready'
|
|
66
|
+
"""
|
|
67
|
+
if not record_id:
|
|
68
|
+
raise ValueError("record_id must not be empty")
|
|
69
|
+
if record_id not in self._records:
|
|
70
|
+
raise NotFoundError(f"Record {record_id} was not found")
|
|
71
|
+
record = self._records[record_id]
|
|
72
|
+
return record.to_dict() if raw else record
|
|
73
|
+
|
|
74
|
+
def list_records(self, *, limit: int = 20, cursor: str | None = None, status: RecordStatus | None = None) -> Page[Record]:
|
|
75
|
+
"""List a single page of records with optional status filtering.
|
|
76
|
+
|
|
77
|
+
Use [iter_records](symbol:orchard.client.Client.iter_records) when you
|
|
78
|
+
want to read every page without managing continuation cursors.
|
|
79
|
+
|
|
80
|
+
Args:
|
|
81
|
+
limit: Maximum number of records in a page, from 1 to 100.
|
|
82
|
+
cursor: Opaque continuation token from an earlier response.
|
|
83
|
+
status: Include only records with this processing status.
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
A page of matching records with an optional continuation cursor.
|
|
87
|
+
|
|
88
|
+
Raises:
|
|
89
|
+
ValueError: If the page size is outside the supported range.
|
|
90
|
+
|
|
91
|
+
Examples:
|
|
92
|
+
>>> page = client.list_records(limit=10, status=RecordStatus.READY)
|
|
93
|
+
>>> titles = page.map(lambda record: record.title)
|
|
94
|
+
"""
|
|
95
|
+
if not 1 <= limit <= 100:
|
|
96
|
+
raise ValueError("limit must be between 1 and 100")
|
|
97
|
+
records = [r for r in self._records.values() if status is None or r.status == status]
|
|
98
|
+
start = int(cursor or "0")
|
|
99
|
+
end = start + limit
|
|
100
|
+
return Page(records[start:end], str(end) if end < len(records) else None, len(records))
|
|
101
|
+
|
|
102
|
+
def iter_records(self, *, page_size: int = 20, status: RecordStatus | None = None) -> Iterator[Record]:
|
|
103
|
+
"""Iterate through records across every page.
|
|
104
|
+
|
|
105
|
+
Pagination is lazy: another page is read only when the iterator needs it.
|
|
106
|
+
Stop iteration early to avoid fetching pages your application won't use.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
page_size: Number of records requested per page, from 1 to 100.
|
|
110
|
+
status: Optional processing status filter.
|
|
111
|
+
|
|
112
|
+
Yields:
|
|
113
|
+
Records in the service's response order.
|
|
114
|
+
|
|
115
|
+
Examples:
|
|
116
|
+
>>> for record in client.iter_records(page_size=50):
|
|
117
|
+
... print(record.id, record.title)
|
|
118
|
+
"""
|
|
119
|
+
cursor = None
|
|
120
|
+
while True:
|
|
121
|
+
page = self.list_records(limit=page_size, cursor=cursor, status=status)
|
|
122
|
+
yield from page.items
|
|
123
|
+
if not page.has_more:
|
|
124
|
+
return
|
|
125
|
+
cursor = page.next_cursor
|
|
126
|
+
|
|
127
|
+
def create_record(self, data: RecordInput, *, idempotency_key: str | None = None) -> Record:
|
|
128
|
+
"""Create a record from a typed input model.
|
|
129
|
+
|
|
130
|
+
Use an idempotency key when retrying a request after a timeout. Reuse the
|
|
131
|
+
same key only for retries of the same logical operation.
|
|
132
|
+
|
|
133
|
+
Args:
|
|
134
|
+
data: Title and labels for the new record.
|
|
135
|
+
idempotency_key: Application-generated retry token.
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
An immutable snapshot of the created record.
|
|
139
|
+
|
|
140
|
+
Examples:
|
|
141
|
+
>>> data = RecordInput(title="Deployment notes", labels={"team": "platform"})
|
|
142
|
+
>>> record = client.create_record(data, idempotency_key="deploy-42")
|
|
143
|
+
"""
|
|
144
|
+
record = Record(f"rec_{len(self._records) + 1}", data.title, labels=data.labels)
|
|
145
|
+
self._records[record.id] = record
|
|
146
|
+
return record
|
|
147
|
+
|
|
148
|
+
def bulk_create(self, records: Sequence[RecordInput], *, batch_size: int = 25) -> list[Record]:
|
|
149
|
+
"""Create multiple records in bounded batches.
|
|
150
|
+
|
|
151
|
+
Args:
|
|
152
|
+
records: Input models to create, in submission order.
|
|
153
|
+
batch_size: Maximum number of records per batch, from 1 to 100.
|
|
154
|
+
|
|
155
|
+
Returns:
|
|
156
|
+
Created records in the same order as the submitted inputs.
|
|
157
|
+
|
|
158
|
+
Raises:
|
|
159
|
+
ValueError: If the batch size is outside the supported range.
|
|
160
|
+
"""
|
|
161
|
+
if not 1 <= batch_size <= 100:
|
|
162
|
+
raise ValueError("batch_size must be between 1 and 100")
|
|
163
|
+
return [self.create_record(item) for item in records]
|
|
164
|
+
|
|
165
|
+
class AsyncClient:
|
|
166
|
+
"""Use the records SDK from an async Python application.
|
|
167
|
+
|
|
168
|
+
Await individual operations, or use `async for` to consume a record iterator.
|
|
169
|
+
This example delegates to an in-memory client; no network calls are made.
|
|
170
|
+
"""
|
|
171
|
+
def __init__(self, api_key: str, *, timeout: float = 10.0):
|
|
172
|
+
"""Configure an async client.
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
api_key: Application credential.
|
|
176
|
+
timeout: Default request timeout, in seconds.
|
|
177
|
+
"""
|
|
178
|
+
self._client = Client(api_key, timeout=timeout)
|
|
179
|
+
|
|
180
|
+
async def fetch(self, record_id: str, *, timeout: float | None = None) -> Record:
|
|
181
|
+
"""Await a typed record response.
|
|
182
|
+
|
|
183
|
+
Args:
|
|
184
|
+
record_id: Stable record identifier.
|
|
185
|
+
timeout: Optional request timeout override, in seconds.
|
|
186
|
+
|
|
187
|
+
Returns:
|
|
188
|
+
The matching record model.
|
|
189
|
+
|
|
190
|
+
Raises:
|
|
191
|
+
NotFoundError: If the record doesn't exist.
|
|
192
|
+
|
|
193
|
+
Examples:
|
|
194
|
+
>>> record = await client.fetch("rec_42")
|
|
195
|
+
"""
|
|
196
|
+
return self._client.fetch(record_id, timeout=timeout)
|
|
197
|
+
|
|
198
|
+
async def iter_records(self, *, page_size: int = 20) -> AsyncIterator[Record]:
|
|
199
|
+
"""Consume paginated records using asynchronous iteration.
|
|
200
|
+
|
|
201
|
+
Args:
|
|
202
|
+
page_size: Maximum number of records read in one page.
|
|
203
|
+
|
|
204
|
+
Yields:
|
|
205
|
+
Typed records from successive pages.
|
|
206
|
+
|
|
207
|
+
Examples:
|
|
208
|
+
>>> async for record in client.iter_records(page_size=50):
|
|
209
|
+
... print(record.title)
|
|
210
|
+
"""
|
|
211
|
+
for record in self._client.iter_records(page_size=page_size):
|
|
212
|
+
yield record
|