Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generate namespace pages #439

Merged
merged 24 commits into from
Nov 28, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
eaa053f
Add api-namespace layout
andrii-balitskyi Nov 22, 2024
0e4639a
Add handlebars helpers
andrii-balitskyi Nov 22, 2024
8d1294d
Introduce setNamespaceLayoutContext
andrii-balitskyi Nov 22, 2024
f910c04
Remove not helper
andrii-balitskyi Nov 22, 2024
3ab2b0c
ci: Generate docs
seambot Nov 22, 2024
158cc2d
Compute namespace resources
andrii-balitskyi Nov 22, 2024
270a06d
Update template, remove toNoCase helper
andrii-balitskyi Nov 22, 2024
4036c16
ci: Generate docs
seambot Nov 22, 2024
b318b39
Make setNamespaceLayoutContext to be responsible only for setting con…
andrii-balitskyi Nov 22, 2024
578e853
Report untitled namespaces
andrii-balitskyi Nov 22, 2024
1fc4f59
Update src/layouts/api-namespace.hbs
andrii-balitskyi Nov 22, 2024
bff636f
Update src/layouts/api-namespace.hbs
andrii-balitskyi Nov 22, 2024
f8140d4
ci: Generate docs
seambot Nov 22, 2024
8cc189b
Update paths.yaml
razor-x Nov 22, 2024
9fadb1e
ci: Generate docs
seambot Nov 22, 2024
02d4b27
Merge branch 'main' of github.com:seamapi/docs into api-namespace-page
andrii-balitskyi Nov 25, 2024
76aece0
ci: Generate docs
seambot Nov 25, 2024
f5921a5
Replace api-clients/acs links with api/acs
andrii-balitskyi Nov 25, 2024
def5b59
Revert .gitbook.yaml
andrii-balitskyi Nov 26, 2024
c3dbdf0
Add resource link
andrii-balitskyi Nov 26, 2024
88c3c5f
ci: Generate docs
seambot Nov 26, 2024
8a1ade2
Improve readability of src/lib/layout/api-namespace.ts
andrii-balitskyi Nov 26, 2024
bc0ce73
Update src/lib/reference.ts
andrii-balitskyi Nov 27, 2024
ed4ae44
ci: Format code
seambot Nov 27, 2024
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
2 changes: 1 addition & 1 deletion docs/SUMMARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@
* [Lock a Lock](api-clients/locks/lock\_door.md)
* [Unlock a Lock](api-clients/locks/unlock\_door.md)
* [List Locks](api-clients/locks/list.md)
* [Access Control Systems](api-clients/acs/README.md)
* [Access Control Systems](api/acs/README.md)
* [Systems](api/acs/systems/README.md)
* [List ACS Systems](api/acs/systems/list.md)
* [Get an ACS System](api/acs/systems/get.md)
Expand Down
1 change: 0 additions & 1 deletion docs/api/_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,6 @@
- `/connected_accounts/get`
- `/connected_accounts/list`
- `/connected_accounts/update`
- `/devices/delete`
- `/devices/get`
- `/devices/list_device_providers`
- `/devices/update`
Expand Down
25 changes: 25 additions & 0 deletions docs/api/acs/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
---
andrii-balitskyi marked this conversation as resolved.
Show resolved Hide resolved
description: Systems for managing and monitoring access to physical spaces
---

# Access Control Systems

## Resources

### [`acs_system`](./systems/README.md#acs_system)
Represents an [access control system](https://docs.seam.co/latest/capability-guides/access-systems).

### [`acs_user`](./users/README.md#acs_user)


### [`acs_entrance`](./entrances/README.md#acs_entrance)
Represents an [entrance](../../capability-guides/access-systems/retrieving-entrance-details.md) within an [access control system](https://docs.seam.co/latest/capability-guides/access-systems).

### [`acs_access_group`](./access_groups/README.md#acs_access_group)
Group that defines the entrances to which a set of users has access and, in some cases, the access schedule for these entrances and users.
The `acs_access_group` object represents an [access group](https://docs.seam.co/latest/capability-guides/access-systems/assigning-users-to-access-groups) within an [access control system](https://docs.seam.co/latest/capability-guides/access-systems).

### [`acs_credential`](./credentials/README.md#acs_credential)
Means by which a user gains access at an entrance.
The `acs_credential` object represents a credential that provides an ACS user access within an access control system. For each acs_credential object, you define the access method. You can also specify additional properties, such as a code.

2 changes: 1 addition & 1 deletion docs/api/acs/users/README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Users
# ACS Users

## `acs_user`

Expand Down
6 changes: 5 additions & 1 deletion src/data/paths.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
---
/acs:
razor-x marked this conversation as resolved.
Show resolved Hide resolved
title: Access Control Systems
description: Systems for managing and monitoring access to physical spaces

/acs/systems:
title: Systems
resources:
- acs_system

/acs/users:
title: Users
title: ACS Users
resources:
- acs_user

Expand Down
13 changes: 13 additions & 0 deletions src/layouts/api-namespace.hbs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
---
description: {{description}}
---

# {{title}}

## Resources

{{#each resources}}
### [`{{name}}`]({{link}})
{{description}}

{{/each}}
10 changes: 9 additions & 1 deletion src/layouts/report.hbs
Original file line number Diff line number Diff line change
@@ -1,7 +1,15 @@
# Documentation Report
{{#if (or noTitle.routes.length noTitle.endpoints.length )}}
{{#if (or noTitle.routes.length noTitle.endpoints.length noTitle.namespaces.length )}}

## Untitled
{{#if noTitle.namespaces.length }}

### Namespaces

{{#each noTitle.namespaces}}
- `{{name}}`
{{/each}}
{{/if}}
{{#if noTitle.routes.length }}

### Routes
Expand Down
10 changes: 10 additions & 0 deletions src/lib/handlebars-helpers.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { capitalCase } from 'change-case'

export const eq = (v1: unknown, v2: unknown): boolean => {
return v1 === v2
}
Expand All @@ -8,3 +10,11 @@ export const or = (...args: unknown[]): boolean => {

return args.some(Boolean)
}

export const add = (v1: number, v2: number): number => {
return v1 + v2
}

export const toCapitalCase = (str: string): string => {
return capitalCase(str)
}
58 changes: 58 additions & 0 deletions src/lib/layout/api-namespace.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import type { Blueprint } from '@seamapi/blueprint'

import type { PathMetadata } from 'lib/path-metadata.js'

export interface ApiNamespaceLayoutContext {
title: string
description: string
resources: Array<{
name: string
description: string
link: string
}>
}

export function setNamespaceLayoutContext(
file: ApiNamespaceLayoutContext,
namespace: string,
resources: Blueprint['resources'],
pathMetadata: PathMetadata,
): void {
const namespaceMetadata = pathMetadata[namespace]
if (namespaceMetadata == null) {
throw new Error(`Namespace metadata for ${namespace} not found`)
}

file.title = namespaceMetadata.title
file.description = namespaceMetadata.description ?? ''

const namespaceRoutes = Object.entries(pathMetadata).filter(([p]) =>
p.startsWith(namespace),
)
const namespaceResources = namespaceRoutes.flatMap(
([_, metadata]) => metadata.resources,
)
file.resources = namespaceResources.map((resourceName) => {
const resource = resources[resourceName]

if (resource == null) {
throw new Error(`Resource ${resourceName} not found in blueprint`)
}

const resourceRoute = namespaceRoutes.find(([_, metadata]) =>
metadata.resources.includes(resourceName),
)
if (resourceRoute == null) {
throw new Error(`Route for resource ${resourceName} not found`)
}
const [routePath] = resourceRoute
const lastPathSegment = routePath.split('/').at(-1)
const docLink = `./${lastPathSegment}/README.md#${resourceName}`

return {
name: resourceName,
description: resource.description,
link: docLink,
}
})
}
1 change: 1 addition & 0 deletions src/lib/layout/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
export * from './api-endpoint.js'
export * from './api-namespace.js'
export * from './api-route.js'
1 change: 1 addition & 0 deletions src/lib/path-metadata.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ export const PathMetadataSchema = z.record(
z.object({
title: z.string().trim().min(1),
resources: z.array(z.string()).default([]),
description: z.string().trim().min(1).optional(),
}),
)

Expand Down
29 changes: 27 additions & 2 deletions src/lib/reference.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import type { Blueprint } from '@seamapi/blueprint'
import type { Blueprint, Route } from '@seamapi/blueprint'
import type Metalsmith from 'metalsmith'

import {
type ApiEndpointLayoutContext,
type ApiNamespaceLayoutContext,
type ApiRouteLayoutContext,
setApiRouteLayoutContext,
setEndpointLayoutContext,
setNamespaceLayoutContext,
} from './layout/index.js'
import { PathMetadataSchema } from './path-metadata.js'

Expand All @@ -14,7 +16,8 @@ const sdks: Array<'javascript'> = []
type Metadata = Partial<Pick<Blueprint, 'routes' | 'resources'>>

type File = ApiEndpointLayoutContext &
ApiRouteLayoutContext & { layout: string }
ApiRouteLayoutContext &
ApiNamespaceLayoutContext & { layout: string }

export const reference = (
files: Metalsmith.Files,
Expand All @@ -35,6 +38,18 @@ export const reference = (
...metadata,
}

const namespacePaths = getNamespacePaths(blueprint.routes)
for (const path of namespacePaths) {
const k = `api${path}/README.md`
files[k] = {
contents: Buffer.from('\n'),
}
const file = files[k] as unknown as File
file.layout = 'api-namespace.hbs'

setNamespaceLayoutContext(file, path, blueprint.resources, pathMetadata)
}

for (const route of blueprint.routes ?? []) {
if (
!route.path.startsWith('/acs') &&
Expand Down Expand Up @@ -79,3 +94,13 @@ export const reference = (
}
}
}

function getNamespacePaths(routes: Route[]): string[] {
return Array.from(
new Set(
routes.flatMap((route) =>
route.namespace != null ? [route.namespace.path] : [],
),
),
)
}
20 changes: 19 additions & 1 deletion src/lib/report.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ interface Report {
deprecated: ReportSection
extraResponseKeys: MissingResponseKeyReport[]
endpointsWithoutCodeSamples: string[]
noTitle: Pick<ReportSection, 'routes' | 'endpoints'>
noTitle: Pick<ReportSection, 'namespaces' | 'routes' | 'endpoints'>
}

interface ReportSection {
Expand Down Expand Up @@ -81,6 +81,7 @@ function generateReport(metadata: Metadata): Report {
extraResponseKeys: [],
endpointsWithoutCodeSamples: [],
noTitle: {
namespaces: [],
routes: [],
endpoints: [],
},
Expand Down Expand Up @@ -204,6 +205,15 @@ function processRoute(route: Route, report: Report, metadata: Metadata): void {
'pathMetadata' in metadata
? PathMetadataSchema.parse(metadata.pathMetadata)
: {}
const namespace = route.namespace
if (
namespace != null &&
pathMetadata[namespace.path]?.title == null &&
!namespace.isUndocumented
) {
addUntitledNamespaceToReport(namespace.path, report)
}

if (pathMetadata[route.path]?.title == null && !route.isUndocumented) {
report.noTitle.routes.push({ name: route.path })
}
Expand All @@ -219,6 +229,14 @@ function processRoute(route: Route, report: Report, metadata: Metadata): void {
}
}

const addUntitledNamespaceToReport = (
namespace: string,
report: Report,
): void => {
if (report.noTitle.namespaces.some((n) => n.name === namespace)) return
report.noTitle.namespaces.push({ name: namespace })
}

function processNamespace(namespace: Namespace, report: Report): void {
const addNamespace = (section: ReportItem[], reason: string): void => {
if (section.some((item) => item.name === namespace.path)) return
Expand Down
Loading