Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 25 additions & 2 deletions packages/core/src/astro-content.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,28 @@
declare module 'astro:content' {
import type { DynamicCollectionEntry } from './types'
export type CollectionKey = string

export function getCollection(name: string): Promise<DynamicCollectionEntry[]>
export interface RenderedContent {
html: string
metadata?: Record<string, unknown>
}

export type CollectionEntry<C extends CollectionKey = CollectionKey> = {
id: string
body?: string
collection: C
data: {
title: string
description?: string
sidebarTitle?: string
icon?: string
badge?: string
prose?: boolean
sortOrder?: number
[key: string]: unknown
}
rendered?: RenderedContent
filePath?: string
}

export function getCollection<C extends CollectionKey>(name: C): Promise<CollectionEntry<C>[]>
}
2 changes: 2 additions & 0 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ export { CodSite } from './site.js'
export type {
AdjacentPage,
AdjacentPages,
BaseEntryData,
BreadcrumbItem,
CodConfig,
CodIntegrationOptions,
CollectionGroupItem,
DynamicCollectionEntry,
EntryDataExtensions,
GroupItem,
PageContext,
PageEntry,
Expand Down
10 changes: 7 additions & 3 deletions packages/core/src/site.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { fetchCollectionEntries, getReferencedCollections, getRouteSlugForEntry,
import { resolveActiveSidebarTree } from './nav.js'
import { buildSidebarTree } from './tree.js'
import type { CodConfig, DynamicCollectionEntry, PageContext, PageEntry, SiteContext, StaticPath } from './types.js'
import { errorToString, normalizeEntryId } from './utils.js'
import { errorToString, getEntryBadge, normalizeEntryId } from './utils.js'

export class CodSite {
#config: CodConfig
Expand Down Expand Up @@ -39,7 +39,10 @@ export class CodSite {
return this.#context
}

async getPageContext(pathname: string, entry: DynamicCollectionEntry): Promise<PageContext> {
async getPageContext<TEntry extends DynamicCollectionEntry>(
pathname: string,
entry: TEntry
): Promise<PageContext<TEntry['data']>> {
const context = await this.getContext()
const title = entry.data.title
const description = entry.data.description
Expand Down Expand Up @@ -98,7 +101,8 @@ function buildPages(config: CodConfig, entriesByCollection: Map<string, DynamicC
slug: getRouteSlugForEntry(config, collection, entry.id),
title: entry.data.title,
}
if (entry.data.method) page.method = entry.data.method
const badge = getEntryBadge(entry)
if (badge) page.badge = badge
pages.push(page)
}
}
Expand Down
13 changes: 11 additions & 2 deletions packages/core/src/tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,15 @@ import type {
TabItem,
} from './types.js'
import { getRouteSlugForEntry } from './content.js'
import { hrefForSlug, lastPathSegment, normalizeEntryId, normalizeSlug, slugifyLabel, titleFromSlug } from './utils.js'
import {
getEntryBadge,
hrefForSlug,
lastPathSegment,
normalizeEntryId,
normalizeSlug,
slugifyLabel,
titleFromSlug,
} from './utils.js'

type EntryLookup = Map<string, DynamicCollectionEntry>

Expand Down Expand Up @@ -143,7 +151,8 @@ function pageFromEntry(path: string, entry: DynamicCollectionEntry | undefined):
path,
}
if (entry?.data.sidebarTitle) node.sidebarTitle = entry.data.sidebarTitle
if (entry?.data.method) node.method = entry.data.method
const badge = getEntryBadge(entry)
if (badge) node.badge = badge
if (entry?.data.icon) node.icon = entry.data.icon
return node
}
Expand Down
45 changes: 26 additions & 19 deletions packages/core/src/types.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import type { CollectionEntry, CollectionKey } from 'astro:content'

export interface CodConfig {
defaultCollection: string
navigation: {
Expand Down Expand Up @@ -26,19 +28,24 @@ export interface CollectionGroupItem {
collection: string
}

export interface DynamicCollectionEntry {
id: string
body?: string
data: {
title: string
description?: string
sidebarTitle?: string
icon?: string
method?: string
prose?: boolean
sortOrder?: number
[key: string]: unknown
}
declare global {
interface CodEntryDataExtensions {}
}

export interface EntryDataExtensions extends CodEntryDataExtensions {}

export interface BaseEntryData extends EntryDataExtensions {
title: string
description?: string
sidebarTitle?: string
icon?: string
badge?: string
prose?: boolean
sortOrder?: number
}

export type DynamicCollectionEntry<TData extends BaseEntryData = BaseEntryData> = CollectionEntry<CollectionKey> & {
data: TData
}

export interface TabInfo {
Expand Down Expand Up @@ -72,7 +79,7 @@ export interface SidebarPageNode {
sidebarTitle?: string
href: string
path: string
method?: string
badge?: string
icon?: string
}

Expand All @@ -94,7 +101,7 @@ export interface BreadcrumbItem {
export interface PageEntry {
slug: string
title: string
method?: string
badge?: string
}

export interface SiteContext {
Expand All @@ -105,8 +112,8 @@ export interface SiteContext {
defaultEntriesBySlug: Map<string, DynamicCollectionEntry>
}

export interface PageContext extends SiteContext {
entry: DynamicCollectionEntry
export interface PageContext<TData extends BaseEntryData = BaseEntryData> extends SiteContext {
entry: DynamicCollectionEntry<TData>
title: string
description: string | undefined
activeTab: string | null
Expand All @@ -116,10 +123,10 @@ export interface PageContext extends SiteContext {
next: AdjacentPage | null
}

export interface StaticPath {
export interface StaticPath<TData extends BaseEntryData = BaseEntryData> {
params: { slug: string | undefined }
props: {
entry: DynamicCollectionEntry
entry: DynamicCollectionEntry<TData>
collectionName: string
}
}
Expand Down
11 changes: 11 additions & 0 deletions packages/core/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -49,3 +49,14 @@ export function pathnameToSlug(pathname: string): string {
export function errorToString(error: unknown): string {
return error instanceof Error ? error.message : String(error)
}

export function getEntryBadge(entry: { data: { badge?: string; openapi?: unknown } } | undefined): string | undefined {
return entry?.data.badge ?? getOpenApiEndpointMethod(entry?.data.openapi)
}

function getOpenApiEndpointMethod(value: unknown): string | undefined {
if (typeof value !== 'object' || value === null || !('endpoint' in value)) return undefined
const endpoint = value.endpoint
if (typeof endpoint !== 'object' || endpoint === null || !('method' in endpoint)) return undefined
return typeof endpoint.method === 'string' ? endpoint.method : undefined
}
2 changes: 1 addition & 1 deletion packages/core/test/core.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ function entriesByCollection(): Map<string, DynamicCollectionEntry[]> {
}

function entry(id: string, title: string, data: Record<string, unknown> = {}): DynamicCollectionEntry {
return { id, body: '', data: { title, ...data } }
return { id, body: '', collection: 'test', data: { title, ...data } }
}

async function makeTempDir(): Promise<string> {
Expand Down
3 changes: 3 additions & 0 deletions packages/openapi/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# cod-openapi

OpenAPI data loading and schemas for Cod.
52 changes: 52 additions & 0 deletions packages/openapi/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"name": "cod-openapi",
"version": "0.0.0",
"type": "module",
"private": true,
"main": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"types": "./dist/index.d.ts",
"default": "./dist/index.js"
},
"./loader": {
"types": "./dist/loader.d.ts",
"default": "./dist/loader.js"
},
"./schema": {
"types": "./dist/schema.d.ts",
"default": "./dist/schema.js"
},
"./types": {
"types": "./dist/types.d.ts",
"default": "./dist/types.js"
},
"./openapi": {
"types": "./dist/openapi.d.ts",
"default": "./dist/openapi.js"
},
"./utils": {
"types": "./dist/utils.d.ts",
"default": "./dist/utils.js"
}
},
"files": [
"dist"
],
"scripts": {
"build": "tsc -p tsconfig.build.json",
"check": "tsc -p tsconfig.json --noEmit",
"test": "bun test"
},
"dependencies": {
"@apidevtools/swagger-parser": "^12.1.0",
"openapi-types": "^12.1.3"
},
"peerDependencies": {
"astro": "^6.0.0"
},
"devDependencies": {
"astro": "^6.4.2"
}
}
Loading