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
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"changes": [
{
"packageName": "@typespec/compiler",
"comment": "",
"type": "none"
}
],
"packageName": "@typespec/compiler"
}
42 changes: 12 additions & 30 deletions common/config/rush/pnpm-lock.yaml

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

14 changes: 7 additions & 7 deletions docs/extending-typespec/emitter-metadata-handling.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,16 +23,16 @@ However, if your emitter does want to split types as OpenAPI does, then it will

These are the main API involved in handling these features. See the linked API reference documentation for more details.

- [`getRequestVisibility(HttpVerb): Visibility`](../standard-library/http/reference/js-api/index.md#getrequestvisibility) - Use this to determine the visibility implied for data in the request parameters or body. Also note that [`Visibility.Read`](../standard-library/http/reference/js-api/enums/Visibility#item) is always applied for response data and therefore there is no corresponding API for the response.
- [`getRequestVisibility(HttpVerb): Visibility`](../standard-library/http/reference/js-api/index.md#getrequestvisibility) - Use this to determine the visibility implied for data in the request parameters or body. Also note that [`Visibility.Read`](../standard-library/http/reference/js-api/Enumeration.Visibility.md#item) is always applied for response data and therefore there is no corresponding API for the response.

- [`MetadataInfo`](../standard-library/http/reference/js-api/interfaces/MetadataInfo.md) - Create this once for each program using [`createMetadataInfo(Program, MetadataInfoOptions)`](../standard-library/http/reference/js-api/index.md#createmetadatainfo) then use it to reason about metadata and visibility implications with the API below.
- [`MetadataInfo`](../standard-library/http/reference/js-api/Interface.MetadataInfo.md) - Create this once for each program using [`createMetadataInfo(Program, MetadataInfoOptions)`](../standard-library/http/reference/js-api/index.md#createmetadatainfo) then use it to reason about metadata and visibility implications with the API below.

- [`MetadataInfo.getEffectivePayloadType(Type, Visibility): Type`](../standard-library/http/reference/js-api/interfaces/MetadataInfo.md#geteffectivepayloadtype) - Use this recursively on every type that is referenced. When given an anonymous model sourced entirely from a single named model after metadata is moved elsewhere or invisible properties are removed, it will recover the named model. This handles the commonly discussed case of seeing that `op something(...Thing)` receives a `Thing` in its request body, but also many other cases.
- [`MetadataInfo.getEffectivePayloadType(Type, Visibility): Type`](../standard-library/http/reference/js-api/Interface.MetadataInfo.md#geteffectivepayloadtype) - Use this recursively on every type that is referenced. When given an anonymous model sourced entirely from a single named model after metadata is moved elsewhere or invisible properties are removed, it will recover the named model. This handles the commonly discussed case of seeing that `op something(...Thing)` receives a `Thing` in its request body, but also many other cases..

- [`MetadataInfo.isTransformed(Model, Visibility)`](../standard-library/http/reference/js-api/interfaces/MetadataInfo.md#istransformed) - Use this to check if a type undergoes any changes in shape due to visibility or metadata. If not, this can allow for simplifications in emit.
- [`MetadataInfo.isTransformed(Model, Visibility)`](../standard-library/http/reference/js-api/Interface.MetadataInfo.md#istransformed) - Use this to check if a type undergoes any changes in shape due to visibility or metadata. If not, this can allow for simplifications in emit.

- [`MetadataInfo.isPayloadProperty(ModelProperty, Visibility): boolean`](../standard-library/http/reference/js-api/interfaces/MetadataInfo.md#ispayloadproperty) - Use this to check if a property is transmitted as an object property in the payload and is not invisible or metadata sent elsewhere.
- [`MetadataInfo.isPayloadProperty(ModelProperty, Visibility): boolean`](../standard-library/http/reference/js-api/Interface.MetadataInfo.md#ispayloadproperty) - Use this to check if a property is transmitted as an object property in the payload and is not invisible or metadata sent elsewhere.

- [`MetadataInfo.isOptional(ModelProperty, Visibility): boolean`](../standard-library/http/reference/js-api/interfaces/MetadataInfo.md#isoptional) - Use this to determine if a property is optional for the given visibility. This will differ from `ModelProperty.isOptional` when the Visibility is Update in which case the property is always considered optional.
- [`MetadataInfo.isOptional(ModelProperty, Visibility): boolean`](../standard-library/http/reference/js-api/Interface.MetadataInfo.md#isoptional) - Use this to determine if a property is optional for the given visibility. This will differ from `ModelProperty.isOptional` when the Visibility is Update in which case the property is always considered optional.

- [`Visibility.Item`](../standard-library/http/reference/js-api/enums/Visibility#item) - Add this flag when recursing into an array. This moves all metadata into the payload, which can be useful in scenarios like batching API calls.
- [`Visibility.Item`](../standard-library/http/reference/js-api/Enumeration.Visibility#item) - Add this flag when recursing into an array. This moves all metadata into the payload, which can be useful in scenarios like batching API calls.
4 changes: 4 additions & 0 deletions packages/compiler/src/core/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -620,6 +620,9 @@ export interface SymbolLinks {
instantiations?: TypeInstantiationMap;
}

/**
* @hidden bug in typedoc
*/
export interface SymbolTable extends ReadonlyMap<string, Sym> {
/**
* Duplicate
Expand Down Expand Up @@ -678,6 +681,7 @@ export interface TypeInstantiationMap {

/**
* A map where keys can be changed without changing enumeration order.
* @hidden bug in typedoc
*/
export interface RekeyableMap<K, V> extends Map<K, V> {
/**
Expand Down
1 change: 1 addition & 0 deletions packages/compiler/src/core/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,6 +342,7 @@ export class MultiKeyMap<K extends readonly object[], V> {
* A map with exactly two keys per value.
*
* Functionally the same as `MultiKeyMap<[K1, K2], V>`, but more efficient.
* @hidden bug in typedoc
*/
export class TwoLevelMap<K1, K2, V> extends Map<K1, Map<K2, V>> {
/**
Expand Down
4 changes: 3 additions & 1 deletion packages/ref-doc/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
],
"dependencies": {
"@typespec/compiler": "workspace:~0.46.0",
"js-yaml": "~4.1.0",
"prettier": "~2.8.7"
},
"devDependencies": {
Expand All @@ -60,13 +61,14 @@
"@types/mocha": "~10.0.1",
"@types/node": "~18.11.9",
"@types/prettier": "2.6.0",
"@types/js-yaml": "~4.0.1",
"c8": "~8.0.0",
"eslint": "^8.42.0",
"mocha-junit-reporter": "~2.2.0",
"mocha-multi-reporters": "~1.5.1",
"mocha": "~10.2.0",
"rimraf": "~5.0.1",
"typedoc-plugin-markdown": "~3.15.1",
"typedoc-plugin-markdown": "~4.0.0-next.17",
"typedoc": "~0.24.8",
"typescript": "~5.1.3"
}
Expand Down
49 changes: 42 additions & 7 deletions packages/ref-doc/src/api-docs.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,38 @@
import { joinPaths } from "@typespec/compiler";
import { writeFile } from "fs/promises";
import { Application } from "typedoc";
import { load } from "typedoc-plugin-markdown";
import { dump } from "js-yaml";
import { Application, DeclarationReflection, PageEvent, ReflectionKind } from "typedoc";
import { PluginOptions, load } from "typedoc-plugin-markdown";
export async function generateJsApiDocs(libraryPath: string, outputDir: string) {
const app = new Application();

loadRenderer(app);
load(app);

const markdownPluginOptions: any = {
entryDocument: "index.md",
readme: "none",
const markdownPluginOptions: Partial<PluginOptions> = {
entryFileName: "index.md",
propertiesFormat: "table",
enumMembersFormat: "table",
typeDeclarationFormat: "table",
hidePageTitle: true,
hideBreadcrumbs: true,
hideKindPrefix: true,
hideInPageTOC: true,
hidePageHeader: true,

tocFormat: "list",
flattenOutputFiles: true,
identifiersAsCodeBlocks: true,
};

app.bootstrap({
name: "JS Api",
entryPoints: [libraryPath],
entryPointStrategy: "legacy-packages",
githubPages: false,
readme: false,
disableSources: true,
readme: "none",
hideGenerator: true,
disableSources: false,
...markdownPluginOptions,
});
const project = app.convert();
Expand All @@ -41,3 +55,24 @@ export async function generateJsApiDocs(libraryPath: string, outputDir: string)
})
);
}

export function loadRenderer(app: Application) {
app.renderer.on(PageEvent.END, (page: PageEvent<DeclarationReflection>) => {
if (page.contents) {
const frontMatter = createFrontMatter(page.model);
page.contents = frontMatter + page.contents.replace(/\\</g, "<");
}
});
}

function createFrontMatter(model: DeclarationReflection) {
return ["---", dump(createFrontMatterData(model)), "---", ""].join("\n");
}

function createFrontMatterData(model: DeclarationReflection) {
const kind = ReflectionKind.singularString(model.kind)[0];
return {
jsApi: true,
title: `[${kind}] ${model.name}`,
};
}