From 2484d2e25c0dbb1400cd84c58e2a09e2d12d4aa8 Mon Sep 17 00:00:00 2001 From: lihbr Date: Wed, 11 Jan 2023 23:10:38 +0100 Subject: [PATCH] docs: add tsdocs --- src/AkteApp.ts | 81 ++++++++++++++++++++++++++++++++++++++++++ src/AkteFiles.ts | 57 +++++++++++++++++++++++++++++ src/defineAkteApp.ts | 8 +++++ src/defineAkteFile.ts | 24 +++++++++++++ src/defineAkteFiles.ts | 29 +++++++++++++++ src/vite/aktePlugin.ts | 5 +++ src/vite/types.ts | 25 +++++++++++++ 7 files changed, 229 insertions(+) diff --git a/src/AkteApp.ts b/src/AkteApp.ts index caf5a99..6c176f0 100644 --- a/src/AkteApp.ts +++ b/src/AkteApp.ts @@ -12,18 +12,51 @@ import { createDebugger } from "./lib/createDebugger"; import { pathToRouterPath } from "./lib/pathToRouterPath"; import { isCLI } from "./lib/isCLI"; +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import type { defineAkteFile } from "./defineAkteFile"; +import type { defineAkteFiles } from "./defineAkteFiles"; + +/* eslint-enable @typescript-eslint/no-unused-vars */ + +/** Akte app configuration object. */ export type Config = { + /** + * Akte files this config is responsible for. + * + * Create them with {@link defineAkteFile} and {@link defineAkteFiles}. + */ files: AkteFiles[]; + + /** Configuration related to Akte build process. */ build?: { + /** + * Output directory for Akte build command. + * + * @remarks + * This directory is overriden by the Akte Vite plugin when running Akte + * through Vite. + * @defaultValue `"dist"` for Akte build command, `".akte"` for Akte Vite plugin. + */ outDir?: string; }; // Most global data will eventually be objects we use this // assumption to make mandatory or not the `globalData` method } & (TGlobalData extends Record ? { + /** + * Global data retrieval function. + * + * The return value of this function is then shared with each Akte file. + */ globalData: GlobalDataFn; } : { + /** + * Global data retrieval function. + * + * The return value of this function is then shared with each Akte file. + */ globalData?: GlobalDataFn; }); @@ -33,6 +66,7 @@ const debugRender = createDebugger("akte:app:render"); const debugRouter = createDebugger("akte:app:router"); const debugCache = createDebugger("akte:app:cache"); +/** An Akte app, ready to be interacted with. */ export class AkteApp { protected config: Config; @@ -46,6 +80,16 @@ export class AkteApp { } } + /** + * Looks up the Akte file responsible for rendering the path. + * + * @param path - Path to lookup, e.g. "/foo" + * @returns A match featuring the path, the path parameters if any, and the + * Akte file. + * @throws {@link NotFoundError} When no Akte file is found for handling + * looked up path. + * @experimental Programmatic API might still change not following SemVer. + */ lookup(path: string): MatchedRoute<{ file: AkteFiles; }> & { path: string } { @@ -65,6 +109,15 @@ export class AkteApp { }; } + /** + * Renders a match from {@link lookup}. + * + * @param match - Match to render. + * @returns Rendered file. + * @throws {@link NotFoundError} When the Akte file could not render the match + * (404), with an optional `cause` attached to it for uncaught errors (500) + * @experimental Programmatic API might still change not following SemVer. + */ async render( match: MatchedRoute<{ file: AkteFiles; @@ -96,6 +149,12 @@ export class AkteApp { } } + /** + * Renders all Akte files. + * + * @returns Rendered files map. + * @experimental Programmatic API might still change not following SemVer. + */ async renderAll(): Promise> { debugRender("rendering all files..."); @@ -146,6 +205,13 @@ export class AkteApp { return files; } + /** + * Writes a map of rendered Akte files to the specified `outDir`, or the app + * specified one (defaults to `"dist"`). + * + * @param args - A map of rendered Akte files, and an optional `outDir` + * @experimental Programmatic API might still change not following SemVer. + */ async writeAll(args: { outDir?: string; files: Record; @@ -195,6 +261,14 @@ export class AkteApp { ); } + /** + * Build (renders and write) all Akte files to the specified `outDir`, or the + * app specified one (defaults to `"dist"`). + * + * @param args - An optional `outDir` + * @returns Built files array. + * @experimental Programmatic API might still change not following SemVer. + */ async buildAll(args?: { outDir?: string }): Promise { const files = await this.renderAll(); await this.writeAll({ ...args, files }); @@ -202,6 +276,13 @@ export class AkteApp { return Object.keys(files); } + /** + * Akte caches all `globalData`, `data`, `bulkData` calls for performance. + * This function can be used to clear the cache. + * + * @param alsoClearFileCache - Also clear cache on all registered Akte files. + * @experimental Programmatic API might still change not following SemVer. + */ clearCache(alsoClearFileCache = false): void { debugCache("clearing..."); diff --git a/src/AkteFiles.ts b/src/AkteFiles.ts index f1c471c..c243b89 100644 --- a/src/AkteFiles.ts +++ b/src/AkteFiles.ts @@ -4,6 +4,12 @@ import { type Awaitable } from "./types"; import { createDebugger } from "./lib/createDebugger"; import { pathToFilePath } from "./lib/pathToFilePath"; +/* eslint-disable @typescript-eslint/no-unused-vars */ + +import type { AkteApp } from "./AkteApp"; + +/* eslint-enable @typescript-eslint/no-unused-vars */ + type Path< TParams extends string[], TPrefix extends string = string, @@ -15,27 +21,74 @@ type Path< ? Path : string; +/** + * A function responsible for fetching the data required to render a given file + * at the provided path. Used for optimization like server side rendering or + * serverless. + */ export type FilesDataFn< TGlobalData, TParams extends string[], TData, > = (context: { + /** Path to get data for. */ path: string; + + /** Path parameters if any. */ params: Record; + + /** Akte app global data. */ globalData: TGlobalData; }) => Awaitable; +/** A function responsible for fetching all the data required to render files. */ export type FilesBulkDataFn = (context: { + /** Akte app global data. */ globalData: TGlobalData; }) => Awaitable>; export type FilesDefinition = { + /** + * Path pattern for the Akte files. + * + * @example + * "/"; + * "/foo"; + * "/bar.json"; + * "/posts/:slug"; + * "/posts/:taxonomy/:slug"; + * "/pages/**"; + * "/assets/**.json"; + */ path: Path; + + /** + * A function responsible for fetching the data required to render a given + * file. Used for optimization like server side rendering or serverless. + * + * Throwing a {@link NotFoundError} makes the file at path to be treated as a + * 404, any other error makes it treated as a 500. + */ data?: FilesDataFn; + + /** A function responsible for fetching all the data required to render files. */ bulkData?: FilesBulkDataFn; + + /** + * A function responsible for rendering + * + * @param context - Resolved file path, app global data, and data to render + * the file. + * @returns Rendered file. + */ render: (context: { + /** Path to render. */ path: string; + + /** Akte app global data. */ globalData: TGlobalData; + + /** File data for path. */ data: TData; }) => Awaitable; }; @@ -52,6 +105,7 @@ export class AkteFiles< > { protected definition: FilesDefinition; + /** Path pattern of this Akte files. */ get path(): string { return this.definition.path; } @@ -62,6 +116,7 @@ export class AkteFiles< debug("created %o", this.path); } + /** @internal Prefer {@link AkteApp.render} or use at your own risks. */ async render(args: { path: string; params: Record; @@ -76,6 +131,7 @@ export class AkteFiles< }); } + /** @internal Prefer {@link AkteApp.renderAll} or use at your own risks. */ async renderAll(args: { globalData: TGlobalData; }): Promise> { @@ -122,6 +178,7 @@ export class AkteFiles< return Object.fromEntries(fileEntries); } + /** @internal Prefer {@link AkteApp.clearCache} or use at your own risks. */ clearCache(): void { this._dataPromiseMap = new Map(); this._bulkDataPromise = undefined; diff --git a/src/defineAkteApp.ts b/src/defineAkteApp.ts index e726d47..c3ee187 100644 --- a/src/defineAkteApp.ts +++ b/src/defineAkteApp.ts @@ -1,5 +1,13 @@ import { AkteApp, type Config } from "./AkteApp"; +/** + * Creates an Akte app from given configuration. + * + * @typeParam TGlobalData - Global data type the app should be configured with + * (inferred by default) + * @param config - Configuration to create the Akte app with. + * @returns The created Akte app. + */ export const defineAkteApp = ( config: Config, ): AkteApp => { diff --git a/src/defineAkteFile.ts b/src/defineAkteFile.ts index 219aacf..4fc58ed 100644 --- a/src/defineAkteFile.ts +++ b/src/defineAkteFile.ts @@ -11,7 +11,31 @@ type FileDefinition = Omit< "bulkData" >; +/** + * Creates an Akte files instance for a single file. + * + * @example + * const posts = defineAkteFile().from({ + * path: "/about", + * data() { + * return {}; + * }, + * render(context) { + * return "..."; + * }, + * }); + * + * @typeParam TGlobalData - Global data the Akte files expects. + * @typeParam TData - Data the Akte files expects (inferred by default) + * @returns A factory to create the Akte files from. + */ export const defineAkteFile = (): { + /** + * Creates an Akte files instance for a single file from a definition. + * + * @param definition - The definition to create the instance from. + * @returns The created Akte files. + */ from: < _TGlobalData extends TGlobalData, _TData extends TData extends Empty diff --git a/src/defineAkteFiles.ts b/src/defineAkteFiles.ts index eab1767..7aeaf19 100644 --- a/src/defineAkteFiles.ts +++ b/src/defineAkteFiles.ts @@ -7,11 +7,40 @@ import { import type { Empty } from "./types"; +/** + * Creates an Akte files instance. + * + * @example + * const posts = defineAkteFiles().from({ + * path: "/posts/:slug", + * bulkData() { + * return { + * "/posts/foo": {}, + * "/posts/bar": {}, + * "/posts/baz": {}, + * }; + * }, + * render(context) { + * return "..."; + * }, + * }); + * + * @typeParam TGlobalData - Global data the Akte files expects. + * @typeParam TParams - Parameters the Akte files expects. + * @typeParam TData - Data the Akte files expects (inferred by default) + * @returns A factory to create the Akte files from. + */ export const defineAkteFiles = < TGlobalData, TParams extends string[] | Empty = Empty, TData = Empty, >(): { + /** + * Creates an Akte files instance from a definition. + * + * @param definition - The definition to create the instance from. + * @returns The created Akte files. + */ from: < _TGlobalData extends TGlobalData, _TParams extends TParams extends Empty diff --git a/src/vite/aktePlugin.ts b/src/vite/aktePlugin.ts index 6cfadf5..f5e5476 100644 --- a/src/vite/aktePlugin.ts +++ b/src/vite/aktePlugin.ts @@ -23,6 +23,11 @@ const DEFAULT_OPTIONS: Omit, "app" | "minifyHTML"> = { const debug = createDebugger("akte:vite", true); +/** + * Akte Vite plugin factory. + * + * @param rawOptions - Plugin options. + */ export const aktePlugin = ( rawOptions: Options, ): PluginOption[] => { diff --git a/src/vite/types.ts b/src/vite/types.ts index b2dd108..ced0476 100644 --- a/src/vite/types.ts +++ b/src/vite/types.ts @@ -2,12 +2,37 @@ import type { Options as MinifyHTMLOptions } from "html-minifier-terser"; import { type AkteApp } from "../AkteApp"; +/** Akte Vite plugin options. */ export type Options = { + /** Akte app to run the plugin with. */ app: AkteApp; + + /** + * Cache file used by Akte during Vite dev and build process. + * + * @remarks + * This file _has_ to be a child directory of Vite's root directory. + * @defaultValue `".akte"` + */ cacheDir?: string; + + /** + * By default Akte Vite plugin will minify Akte generated HTML upon Vite build + * using `html-minifier-terser`. + * {@link https://github.com/lihbr/akte/blob/master/src/vite/aktePlugin.ts#L8-L18 Sensible defaults are used by default}. + * + * You can use this option to provide additional parameters to + * `html-minifier-terser`, + * {@link https://github.com/terser/html-minifier-terser#minification-comparison see its documentation}. + * + * @remarks + * When enabled, `html-minifier-terser` needs to be installed separately as a + * development dependency for the build process to succeed. + */ minifyHTML?: boolean | MinifyHTMLOptions; }; +/** @internal */ export type ResolvedOptions = { app: AkteApp; cacheDir: string;