diff --git a/change/@microsoft-fast-element-d3208e54-7afa-44a5-9763-acecac743653.json b/change/@microsoft-fast-element-d3208e54-7afa-44a5-9763-acecac743653.json new file mode 100644 index 00000000000..8bba6196a33 --- /dev/null +++ b/change/@microsoft-fast-element-d3208e54-7afa-44a5-9763-acecac743653.json @@ -0,0 +1,7 @@ +{ + "type": "none", + "comment": "Add api-extractor generated docs for di and context export paths", + "packageName": "@microsoft/fast-element", + "email": "7559015+janechu@users.noreply.github.com", + "dependentChangeType": "none" +} diff --git a/packages/web-components/fast-element/api-extractor.context.json b/packages/web-components/fast-element/api-extractor.context.json new file mode 100644 index 00000000000..96748e457b0 --- /dev/null +++ b/packages/web-components/fast-element/api-extractor.context.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + "extends": "../../../api-extractor.json", + "mainEntryPointFilePath": "./dist/dts/context.d.ts", + "apiReport": { + "enabled": true, + "reportFolder": "/docs/context", + "reportFileName": "api-report.md" + }, + "docModel": { + "enabled": true, + "apiJsonFilePath": "/dist/context/context.api.json" + } + } \ No newline at end of file diff --git a/packages/web-components/fast-element/api-extractor.di.json b/packages/web-components/fast-element/api-extractor.di.json new file mode 100644 index 00000000000..eb937082a00 --- /dev/null +++ b/packages/web-components/fast-element/api-extractor.di.json @@ -0,0 +1,14 @@ +{ + "$schema": "https://developer.microsoft.com/json-schemas/api-extractor/v7/api-extractor.schema.json", + "extends": "../../../api-extractor.json", + "mainEntryPointFilePath": "./dist/dts/di/di.d.ts", + "apiReport": { + "enabled": true, + "reportFolder": "/docs/di", + "reportFileName": "api-report.md" + }, + "docModel": { + "enabled": true, + "apiJsonFilePath": "/dist/di/di.api.json" + } + } \ No newline at end of file diff --git a/packages/web-components/fast-element/docs/context/api-report.md b/packages/web-components/fast-element/docs/context/api-report.md new file mode 100644 index 00000000000..8e3e2f53b22 --- /dev/null +++ b/packages/web-components/fast-element/docs/context/api-report.md @@ -0,0 +1,69 @@ +## API Report File for "@microsoft/fast-element" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +// @public +export type Context = { + readonly name: string; + readonly initialValue?: T; +}; + +// @public +export const Context: Readonly<{ + eventType: "context-request"; + for(name: string): FASTContext; + create(name: string, initialValue?: T_1 | undefined): FASTContext; + setDefaultRequestStrategy(strategy: FASTContextRequestStrategy): void; + get(target: EventTarget, context: T_2): ContextType; + request(target: EventTarget, context: T_3, callback: ContextCallback>, multiple?: boolean): void; + dispatch(target: EventTarget, context: T_4, callback: ContextCallback>, multiple?: boolean): void; + provide(target: EventTarget, context: T_5, value: ContextType): void; + handle(target: EventTarget, callback: (event: ContextEvent) => void, context?: T_6 | undefined): void; + defineProperty(target: Constructable | EventTarget, propertyName: string, context: T_7): void; +}>; + +// @public +export type ContextCallback = (value: ValueType, dispose?: () => void) => void; + +// Warning: (ae-forgotten-export) The symbol "ParameterDecorator" needs to be exported by the entry point context.d.ts +// +// @public +export type ContextDecorator = Readonly> & PropertyDecorator & ParameterDecorator_2; + +// @public +export class ContextEvent extends Event { + constructor(context: T, callback: ContextCallback>, multiple?: boolean | undefined); + // (undocumented) + readonly callback: ContextCallback>; + // (undocumented) + readonly context: T; + // (undocumented) + readonly multiple?: boolean | undefined; +} + +// @public +export type ContextType = T extends Context ? Y : never; + +// @public +export type FASTContext = ContextDecorator & { + get(target: EventTarget): T; + provide(target: EventTarget, value: T): void; + request(target: EventTarget, callback: ContextCallback, multiple?: boolean): void; + handle(target: EventTarget, callback: (event: ContextEvent>) => void): void; +}; + +// @public +export type FASTContextRequestStrategy = (target: EventTarget, context: T, callback: ContextCallback>, multiple: any) => void; + +// @public +export type UnknownContext = Context; + +// Warnings were encountered during analysis: +// +// dist/dts/context.d.ts:127:5 - (ae-forgotten-export) The symbol "Constructable" needs to be exported by the entry point context.d.ts + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/web-components/fast-element/docs/di/api-report.md b/packages/web-components/fast-element/docs/di/api-report.md new file mode 100644 index 00000000000..6ee503bc3be --- /dev/null +++ b/packages/web-components/fast-element/docs/di/api-report.md @@ -0,0 +1,315 @@ +## API Report File for "@microsoft/fast-element" + +> Do not edit this file. It is a report generated by [API Extractor](https://api-extractor.com/). + +```ts + +// @public +export const all: (key: any, searchAncestors?: boolean) => ReturnType; + +// @public +export type AsyncRegistrationLocator = (key: Key) => Promise; + +// @public +export interface Container extends ServiceLocator { + createChild(config?: Partial>): Container; + getFactory(key: T): Factory; + getResolver(key: K | Key, autoRegister?: boolean): Resolver | null; + register(...params: any[]): Container; + // Warning: (ae-forgotten-export) The symbol "Constructable" needs to be exported by the entry point di.d.ts + registerFactory(key: T, factory: Factory): void; + registerResolver(key: K, resolver: Resolver): Resolver; + registerTransformer(key: K, transformer: Transformer_2): boolean; +} + +// Warning: (ae-forgotten-export) The symbol "ContextDecorator" needs to be exported by the entry point di.d.ts +// +// @public +export const Container: ContextDecorator; + +// @public +export interface ContainerConfiguration { + asyncRegistrationLocator: AsyncRegistrationLocator; + defaultResolver(key: Key, handler: Container): Resolver; + parentLocator: ParentLocator; + responsibleForOwnerRequests: boolean; +} + +// @public +export const ContainerConfiguration: Readonly<{ + default: Readonly; +}>; + +// Warning: (ae-internal-missing-underscore) The name "ContainerImpl" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal (undocumented) +export class ContainerImpl implements DOMContainer { + constructor(owner: any, config: ContainerConfiguration); + // (undocumented) + protected config: ContainerConfiguration; + // (undocumented) + createChild(config?: Partial>): Container; + // (undocumented) + get depth(): number; + // (undocumented) + get(key: K): Resolved; + // (undocumented) + getAll(key: K, searchAncestors?: boolean): readonly Resolved[]; + // (undocumented) + getAsync(key: K): Promise>; + // (undocumented) + getFactory(Type: K): Factory; + // (undocumented) + getResolver(key: K | Key, autoRegister?: boolean): Resolver | null; + // (undocumented) + handleContextRequests(enable: boolean): void; + // (undocumented) + has(key: K, searchAncestors?: boolean): boolean; + // (undocumented) + protected owner: any; + // (undocumented) + get parent(): ContainerImpl | null; + // (undocumented) + register(...params: any[]): Container; + // (undocumented) + registerFactory(key: K, factory: Factory): void; + // (undocumented) + registerResolver(key: K, resolver: Resolver): Resolver; + // (undocumented) + registerTransformer(key: K, transformer: Transformer_2): boolean; + // (undocumented) + get responsibleForOwnerRequests(): boolean; +} + +// @public +export const DefaultResolver: Readonly<{ + none(key: Key): Resolver; + singleton(key: Key): Resolver; + transient(key: Key): Resolver; +}>; + +// @public +export const DI: Readonly<{ + installAsContextRequestStrategy(fallback?: () => DOMContainer): void; + createContainer(config?: Partial): Container; + findResponsibleContainer(target: EventTarget, fallback?: () => DOMContainer): DOMContainer; + findParentContainer(target: EventTarget, fallback?: () => DOMContainer): DOMContainer; + getOrCreateDOMContainer(target?: EventTarget, config?: Partial>): DOMContainer; + getDependencies(Type: Constructable | Injectable): Key[]; + defineProperty(target: {}, propertyName: string, key: Key, respectConnection?: boolean): void; + createContext: typeof createContext; + inject(...dependencies: Key[]): (target: any, key?: string | number, descriptor?: PropertyDescriptor | number) => void; + transient>(target: T & Partial>): T & RegisterSelf; + singleton>(target: T_1 & Partial>, options?: SingletonOptions): T_1 & RegisterSelf; +}>; + +// @public +export interface DOMContainer extends Container { + // @beta + handleContextRequests(enable: boolean): void; +} + +// @public +export const DOMContainer: ContextDecorator; + +// @public +export interface Factory { + construct(container: Container, dynamicDependencies?: Key[]): Resolved; + constructAsync(container: Container, dynamicDependencies?: Key[]): Promise>; + registerTransformer(transformer: Transformer_2): void; + readonly Type: T; +} + +// Warning: (ae-internal-missing-underscore) The name "FactoryImpl" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal (undocumented) +export class FactoryImpl implements Factory { + constructor(Type: T, dependencies: Key[]); + // (undocumented) + construct(container: Container, dynamicDependencies?: Key[]): Resolved; + // (undocumented) + constructAsync(container: Container, dynamicDependencies?: Key[]): Promise>; + // (undocumented) + registerTransformer(transformer: (instance: any) => any): void; + // (undocumented) + Type: T; +} + +// @public +export function ignore(target: Injectable, property?: string | number, descriptor?: PropertyDescriptor | number): void; + +// @public +export const inject: (...dependencies: Key[]) => (target: any, key?: string | number, descriptor?: PropertyDescriptor | number) => void; + +// @public +export type Injectable = Constructable & { + inject?: Key[]; +}; + +// @public +export interface InterfaceConfiguration { + friendlyName?: string; + respectConnection?: boolean; +} + +// @public +export type Key = PropertyKey | object | ContextDecorator | Constructable | Resolver; + +// @public +export const lazy: (key: any) => any; + +// @public +export const newInstanceForScope: (key: any) => any; + +// @public +export const newInstanceOf: (key: any) => any; + +// @public +export const optional: (key: any) => any; + +// @public +export type ParentLocator = (owner: any) => Container | null; + +// @public +export type RegisterSelf = { + register(container: Container): Resolver>; + registerInRequestor: boolean; +}; + +// @public +export interface Registration { + register(container: Container): Resolver; +} + +// @public +export const Registration: Readonly<{ + instance(key: Key, value: T): Registration; + singleton>(key: Key, value: T_1): Registration>; + transient>(key: Key, value: T_2): Registration>; + callback(key: Key, callback: ResolveCallback): Registration>; + cachedCallback(key: Key, callback: ResolveCallback): Registration>; + aliasTo(originalKey: T_5, aliasKey: Key): Registration>; +}>; + +// @public +export interface Registry { + register(container: Container, ...params: unknown[]): void | Resolver; +} + +// @public +export type ResolveCallback = (handler: Container, requestor: Container, resolver: Resolver) => T; + +// Warning: (ae-forgotten-export) The symbol "ResolverLike" needs to be exported by the entry point di.d.ts +// +// @public +export type Resolved = K extends ContextDecorator ? T : K extends Constructable ? InstanceType : K extends ResolverLike ? T1 extends Constructable ? InstanceType : T1 : K; + +// @public +export interface Resolver extends ResolverLike { +} + +// @public +export class ResolverBuilder { + constructor(container: Container, key: Key); + aliasTo(destinationKey: Key): Resolver; + cachedCallback(value: ResolveCallback): Resolver; + callback(value: ResolveCallback): Resolver; + instance(value: K): Resolver; + singleton(value: Constructable): Resolver; + transient(value: Constructable): Resolver; +} + +// Warning: (ae-internal-missing-underscore) The name "ResolverImpl" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal (undocumented) +export class ResolverImpl implements Resolver, Registration { + // (undocumented) + get $isResolver(): true; + constructor(key: Key, strategy: ResolverStrategy, state: any); + // (undocumented) + getFactory(container: Container): Factory | null; + // (undocumented) + key: Key; + // (undocumented) + register(container: Container): Resolver; + // (undocumented) + resolve(handler: Container, requestor: Container): any; + // (undocumented) + resolveAsync(handler: Container, requestor: Container): Promise; + // (undocumented) + state: any; + // (undocumented) + strategy: ResolverStrategy; +} + +// Warning: (ae-internal-missing-underscore) The name "ResolverStrategy" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal (undocumented) +export const enum ResolverStrategy { + // (undocumented) + alias = 5, + // (undocumented) + array = 4, + // (undocumented) + callback = 3, + // (undocumented) + instance = 0, + // (undocumented) + singleton = 1, + // (undocumented) + transient = 2 +} + +// @public +export interface ServiceLocator { + get(key: K): Resolved; + get(key: Key): Resolved; + get(key: K | Key): Resolved; + getAll(key: K, searchAncestors?: boolean): readonly Resolved[]; + getAll(key: Key, searchAncestors?: boolean): readonly Resolved[]; + getAll(key: K | Key, searchAncestors?: boolean): readonly Resolved[]; + getAsync(key: K): Promise>; + getAsync(key: Key): Promise>; + getAsync(key: K | Key): Promise>; + has(key: K | Key, searchAncestors: boolean): boolean; +} + +// @public +export const ServiceLocator: ContextDecorator; + +// Warning: (ae-forgotten-export) The symbol "singletonDecorator" needs to be exported by the entry point di.d.ts +// +// @public +export function singleton(): typeof singletonDecorator; + +// @public (undocumented) +export function singleton(options?: SingletonOptions): typeof singletonDecorator; + +// @public +export function singleton(target: T & Partial>): T & RegisterSelf; + +// @public +type Transformer_2 = (instance: Resolved) => Resolved; +export { Transformer_2 as Transformer } + +// Warning: (ae-forgotten-export) The symbol "transientDecorator" needs to be exported by the entry point di.d.ts +// +// @public +export function transient(): typeof transientDecorator; + +// @public +export function transient(target: T & Partial>): T & RegisterSelf; + +// Warning: (ae-internal-missing-underscore) The name "validateKey" should be prefixed with an underscore because the declaration is marked as @internal +// +// @internal (undocumented) +export function validateKey(key: any): void; + +// Warnings were encountered during analysis: +// +// dist/dts/di/di.d.ts:479:5 - (ae-forgotten-export) The symbol "createContext" needs to be exported by the entry point di.d.ts +// dist/dts/di/di.d.ts:540:5 - (ae-forgotten-export) The symbol "SingletonOptions" needs to be exported by the entry point di.d.ts + +// (No @packageDocumentation comment for this package) + +``` diff --git a/packages/web-components/fast-element/package.json b/packages/web-components/fast-element/package.json index 0ec48477a79..d54a57c95c8 100644 --- a/packages/web-components/fast-element/package.json +++ b/packages/web-components/fast-element/package.json @@ -95,7 +95,9 @@ "clean:dist": "node ../../../build/clean.js dist", "doc": "api-extractor run --local", "doc:ci": "api-extractor run", - "build": "npm run build:tsc && npm run build:rollup && npm run doc", + "doc:exports": "node ./scripts/run-api-extractor.js", + "doc:exports:ci": "node ./scripts/run-api-extractor.js ci", + "build": "npm run build:tsc && npm run build:rollup && npm run doc && npm run doc:exports", "build:rollup": "rollup -c", "build:tsc": "tsc -p ./tsconfig.json", "dev": "tsc -p ./tsconfig.json -w", @@ -105,7 +107,7 @@ "prettier:diff": "prettier --config ../../../.prettierrc \"**/*.ts\" --list-different", "eslint": "eslint . --ext .ts", "eslint:fix": "eslint . --ext .ts --fix", - "test": "npm run eslint && npm run test-chrome:verbose && npm run doc:ci", + "test": "npm run eslint && npm run test-chrome:verbose && npm run doc:ci && npm run doc:exports:ci", "test-node": "mocha --reporter min --exit dist/esm/__test__/setup-node.js './dist/esm/**/*.spec.js'", "test-node:verbose": "mocha --reporter spec --exit dist/esm/__test__/setup-node.js './dist/esm/**/*.spec.js'", "test-chrome": "karma start karma.conf.cjs --browsers=ChromeHeadlessOpt --single-run --coverage", diff --git a/packages/web-components/fast-element/scripts/run-api-extractor.js b/packages/web-components/fast-element/scripts/run-api-extractor.js new file mode 100644 index 00000000000..1875e610a94 --- /dev/null +++ b/packages/web-components/fast-element/scripts/run-api-extractor.js @@ -0,0 +1,51 @@ +import path from "path"; +import fs from "fs"; +import { fileURLToPath } from 'url'; +import { Extractor, ExtractorConfig } from '@microsoft/api-extractor'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); + +export const exportPaths = [ + { + path: "./context.js", + docsFolder: "context", + configPath: path.resolve(__dirname, "../api-extractor.context.json") + }, + { + path: "./di.js", + docsFolder: "di", + configPath: path.resolve(__dirname, "../api-extractor.di.json") + } +]; + +(function() { + exportPaths.forEach((exportPath) => { + const docsFolder = path.resolve(__dirname, `../docs/${exportPath.docsFolder}`); + // Create folders in the docs directory + if (!fs.existsSync(docsFolder)) { + fs.mkdirSync(docsFolder); + } + + // Load and parse the api-extractor.json file + const extractorConfig = ExtractorConfig.loadFileAndPrepare(exportPath.configPath); + + // Invoke API Extractor + const extractorResult = Extractor.invoke( + extractorConfig, + { + // Equivalent to the "--local" command-line parameter + localBuild: process.argv[2] !== "ci", + } + ); + + if (extractorResult.succeeded) { + console.log(`API Extractor completed successfully for ${exportPath.configPath}`); + } else { + console.error( + `API Extractor completed with ${extractorResult.errorCount} errors` + + ` and ${extractorResult.warningCount} warnings for ${exportPath.configPath}` + ); + } + }); +})(); diff --git a/sites/website/sidebars.js b/sites/website/sidebars.js index 5d74b5931f6..c393fe3143b 100644 --- a/sites/website/sidebars.js +++ b/sites/website/sidebars.js @@ -54,6 +54,7 @@ module.exports = { items: [ { type: "doc", + label: "@microsoft/fast-element", id: "api/fast-element", customProps: { description: @@ -61,6 +62,22 @@ module.exports = { keywords: ["fast-element"], }, }, + { + type: "doc", + label: "@microsoft/fast-element/context.js", + id: "api/fast-element/context/fast-element", + customProps: { + keywords: ["context"], + }, + }, + { + type: "doc", + label: "@microsoft/fast-element/di.js", + id: "api/fast-element/di/fast-element", + customProps: { + keywords: ["dependency injection"], + }, + } ], }, { diff --git a/sites/website/src/generate-docs.js b/sites/website/src/generate-docs.js index 0c5679b8a50..db512d28b12 100644 --- a/sites/website/src/generate-docs.js +++ b/sites/website/src/generate-docs.js @@ -31,17 +31,15 @@ function findFiles(startPath, filter, paths = []) { return paths; } -const packages = ["fast-element"]; - -function identifyPackage(path) { - for (const pkg of packages) { - if (path.indexOf(pkg) !== -1) { - return pkg; - } +const packages = [ + { + main: "fast-element", + exports: [ + "context", + "di" + ] } - - return ""; -} +]; function updateContentForMdx(content) { content = content.replace("{", "{"); @@ -222,40 +220,32 @@ async function copyArticleMarkdown() { } } -// Copy the api.json files from the web-components packages. +// Copy the api.json files from the packages. async function copyAPI() { for (const pkg of packages) { await safeCopy( path.resolve( - getPackageJsonDir(`@microsoft/${pkg}`), - `./dist/${pkg}.api.json` + getPackageJsonDir(`@microsoft/${pkg.main}`), + `./dist/${pkg.main}.api.json` ), - // require.resolve(`@microsoft/${pkg}/dist/${pkg}.api.json`), - `./src/docs/api/${pkg}.api.json` + `./src/docs/api/${pkg.main}.api.json` ); - } -} -async function buildAPIMarkdown() { - await copyAPI(); - - await new Promise((resolve, reject) => - exec( - "api-documenter markdown -i src/docs/api -o docs/api", - (err, stdout, stderr) => { - console.log(stdout); - console.error(stderr); - if (err) { - return reject(err); - } - - return resolve(); + if (Array.isArray(pkg.exports)) { + for (const pkgExport of pkg.exports) { + await safeCopy( + path.resolve( + getPackageJsonDir(`@microsoft/${pkg.main}`), + `./dist/${pkgExport}/${pkgExport}.api.json` + ), + `./src/docs/api/${pkg.main}/${pkgExport}/${pkgExport}.api.json` + ); } - ) - ); + } + } +} - const dir = "./docs/api"; - const docFiles = await fs.readdir(dir); +async function convertDocFiles(dir, docFiles, package, exportPath) { for (const docFile of docFiles) { try { const { name: id, ext } = path.parse(docFile); @@ -263,8 +253,7 @@ async function buildAPIMarkdown() { continue; } - const pkg = identifyPackage(docFile); - const isAPIHome = id === pkg; + const isAPIHome = !id.includes("."); const docPath = path.join(dir, docFile); const input = fs.createReadStream(docPath); const output = []; @@ -290,6 +279,10 @@ async function buildAPIMarkdown() { } } + if (package && exportPath) { + line = line.replace(package, `${package}/${exportPath}`); + } + const homeLink = line.match(/\[Home\]\(.\/index\.md\) > (.*)/); if (homeLink) { @@ -313,7 +306,7 @@ async function buildAPIMarkdown() { "---", `id: ${id}`, `title: ${title}`, - `hide_title: ${!isAPIHome}`, + `hide_title: ${isAPIHome}`, "---", ]; @@ -324,6 +317,58 @@ async function buildAPIMarkdown() { } } +async function buildAPIMarkdown() { + await copyAPI(); + + await new Promise((resolve, reject) => + exec( + "api-documenter markdown -i src/docs/api -o docs/api", + (err, stdout, stderr) => { + console.log(stdout); + console.error(stderr); + if (err) { + return reject(err); + } + + return resolve(); + } + ) + ); + + for (const pkg of packages) { + for (const pkgExport of pkg.exports) { + await new Promise((resolve, reject) => + exec( + `api-documenter markdown -i src/docs/api/${pkg.main}/${pkgExport} -o docs/api/${pkg.main}/${pkgExport}`, + (err, stdout, stderr) => { + console.log(stdout); + console.error(stderr); + if (err) { + return reject(err); + } + + return resolve(); + } + ) + ); + } + } + + const dir = "./docs/api"; + const docFiles = await fs.readdir(dir); + + convertDocFiles(dir, docFiles); + + for (const pkg of packages) { + for (const pkgExport of pkg.exports) { + const exportDir = `./docs/api/${pkg.main}/${pkgExport}`; + const exportDocFiles = await fs.readdir(exportDir); + + convertDocFiles(exportDir, exportDocFiles, `@microsoft/${pkg.main}`, `${pkgExport}.js`); + } + } +} + async function main() { await Promise.all([copyArticleMarkdown(), buildAPIMarkdown()]); }