diff --git a/.prettierignore b/.prettierignore index 592c0159ccd1ed4..1964ebfea166f99 100644 --- a/.prettierignore +++ b/.prettierignore @@ -5,4 +5,5 @@ dist public/__redirects public/analytics/static/downloads/main.css src/content/workers-ai-models/*.json -src/content/partials/images/*.mdx \ No newline at end of file +src/content/partials/images/*.mdx +src/content/style-guide/components/*.mdx \ No newline at end of file diff --git a/package-lock.json b/package-lock.json index 83631c24aa0d8db..89361fe4a3a2d8d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -109,6 +109,7 @@ "tailwindcss": "4.1.4", "tippy.js": "6.3.7", "ts-blank-space": "0.6.2", + "ts-morph": "26.0.0", "tsx": "4.20.5", "typescript": "5.9.2", "typescript-eslint": "8.41.0", @@ -1138,13 +1139,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.27.1.tgz", - "integrity": "sha512-I0dZ3ZpCrJ1c04OqlNsQcKiZlsrXf/kkE4FXzID9rIOYICsAbA8mMDzhW/luRNAHdCNt7os/u8wenklZDlUVUQ==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.4.tgz", + "integrity": "sha512-yZbBqeM6TkpP9du/I2pUZnJsRMGGvOuIrhjzC1AwHwW+6he4mni6Bp/m8ijn0iOuZuPI2BfkCoSRunpyjnrQKg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.27.1" + "@babel/types": "^7.28.4" }, "bin": { "parser": "bin/babel-parser.js" @@ -1240,9 +1241,9 @@ } }, "node_modules/@babel/types": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.27.1.tgz", - "integrity": "sha512-+EzkxvLNfiUeKMgy/3luqfsCWFRXLb7U6wNQTk60tovuckwB15B191tJWvpp4HjiQWdJkCxO3Wbvc6jlk3Xb2Q==", + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.4.tgz", + "integrity": "sha512-bkFqkLhh3pMBUQQkpVgWDWq/lqzc2678eUyDlTBhRqhCHFguYYGM0Efga7tYk4TogG/3x0EEl66/OQ+WGbWB/Q==", "dev": true, "license": "MIT", "dependencies": { @@ -3195,6 +3196,29 @@ "url": "https://opencollective.com/libvips" } }, + "node_modules/@isaacs/balanced-match": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/balanced-match/-/balanced-match-4.0.1.tgz", + "integrity": "sha512-yzMTt9lEb8Gv7zRioUilSglI0c0smZ9k5D65677DLWLtWJaXIS3CqcGyUFByYKlnUj6TkjLVs54fBl6+TiGQDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "20 || >=22" + } + }, + "node_modules/@isaacs/brace-expansion": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/@isaacs/brace-expansion/-/brace-expansion-5.0.0.tgz", + "integrity": "sha512-ZT55BDLV0yv0RBm2czMiZ+SqCGO7AvmOM3G/w2xhVPH+te0aKgFjmBvGlL1dH+ql2tgGO3MVrbb3jCKyvpgnxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@isaacs/balanced-match": "^4.0.1" + }, + "engines": { + "node": "20 || >=22" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", @@ -4574,6 +4598,34 @@ "node": ">=10.13.0" } }, + "node_modules/@ts-morph/common": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/@ts-morph/common/-/common-0.27.0.tgz", + "integrity": "sha512-Wf29UqxWDpc+i61k3oIOzcUfQt79PIT9y/MWfAGlrkjg6lBC1hwDECLXPVJAhWjiGbfBCxZd65F/LIZF3+jeJQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-glob": "^3.3.3", + "minimatch": "^10.0.1", + "path-browserify": "^1.0.1" + } + }, + "node_modules/@ts-morph/common/node_modules/minimatch": { + "version": "10.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.3.tgz", + "integrity": "sha512-IPZ167aShDZZUMdRk66cyQAW3qr0WzbHkPdMYa8bzZhlHhO3jALbKdxcaak7W9FfT2rZNpQuUu4Od7ILEpXSaw==", + "dev": true, + "license": "ISC", + "dependencies": { + "@isaacs/brace-expansion": "^5.0.0" + }, + "engines": { + "node": "20 || >=22" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/@types/acorn": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/@types/acorn/-/acorn-4.0.6.tgz", @@ -7652,6 +7704,13 @@ "node": ">=6" } }, + "node_modules/code-block-writer": { + "version": "13.0.3", + "resolved": "https://registry.npmjs.org/code-block-writer/-/code-block-writer-13.0.3.tgz", + "integrity": "sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg==", + "dev": true, + "license": "MIT" + }, "node_modules/codeowners-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/codeowners-utils/-/codeowners-utils-1.0.2.tgz", @@ -18346,6 +18405,17 @@ "node": ">=6.10" } }, + "node_modules/ts-morph": { + "version": "26.0.0", + "resolved": "https://registry.npmjs.org/ts-morph/-/ts-morph-26.0.0.tgz", + "integrity": "sha512-ztMO++owQnz8c/gIENcM9XfCEzgoGphTv+nKpYNM1bgsdOVC/jRZuEBf6N+mLLDNg68Kl+GgUZfOySaRiG1/Ug==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ts-morph/common": "~0.27.0", + "code-block-writer": "^13.0.3" + } + }, "node_modules/tsconfck": { "version": "3.1.5", "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.5.tgz", diff --git a/package.json b/package.json index bdadeed2748a835..2a6fda53492e81e 100644 --- a/package.json +++ b/package.json @@ -127,6 +127,7 @@ "tailwindcss": "4.1.4", "tippy.js": "6.3.7", "ts-blank-space": "0.6.2", + "ts-morph": "26.0.0", "tsx": "4.20.5", "typescript": "5.9.2", "typescript-eslint": "8.41.0", diff --git a/src/components/WorkersTypesInterface.astro b/src/components/WorkersTypesInterface.astro new file mode 100644 index 000000000000000..a1b6d7080d6e6e8 --- /dev/null +++ b/src/components/WorkersTypesInterface.astro @@ -0,0 +1,137 @@ +--- +import { JSDocTagInfo, Project } from "ts-morph"; +import RawTypes from "@cloudflare/workers-types/experimental/index.d.ts?raw"; +import { marked } from "marked"; +import AnchorHeading from "./AnchorHeading.astro"; +import Type from "./Type.astro"; +import { Code } from "@astrojs/starlight/components"; +import { z } from "astro:schema"; + +type Props = z.input; + +const props = z + .object({ + name: z.string(), + }) + .strict(); + +const { name: interfaceName } = props.parse(Astro.props); + +function JSDocToMarkdown(jsdoc: JSDocTagInfo[]) { + return marked.parse( + jsdoc + .map((tag) => { + return tag + .getText() + .filter((part) => part.kind === "text") + .map((part) => { + return part.text; + }) + .join(" "); + }) + .join("\n"), + { async: false }, + ); +} + +const project = new Project(); +const sourceFile = project.createSourceFile("index.d.ts", RawTypes); + +const int = sourceFile.getInterface(interfaceName); + +if (!int) { + throw new Error( + `[WorkersTypesInterface] Could not find interface "${interfaceName}"`, + ); +} + +const methods = int.getMethods(); + +if (!methods || methods.length === 0) { + throw new Error( + `[WorkersTypesInterface] Could not find any methods for interface "${interfaceName}"`, + ); +} +--- + + + + +{ + methods.map((method) => { + const methodName = method.getName(); + const signature = method.getSignature(); + + if (!signature) { + throw new Error( + `[WorkersTypesInterface] Could not find signature for method "${interfaceName}#${methodName}"`, + ); + } + + const comment = signature + .getDocumentationComments() + .map((comment) => { + return comment.getText(); + }) + .join("\n"); + + const jsdoc = signature.getJsDocTags(); + const returnsJsdoc = jsdoc.find((tag) => tag.getName() === "returns"); + + const parameters = signature.getParameters(); + const returns = signature.getReturnType(); + + return ( + <> + +

{comment}

+ + + +
    + {parameters?.map((param) => { + const type = param.getDeclarations()[0].getType(); + const jsdoc = param.getJsDocTags(); + + const markdown = JSDocToMarkdown(jsdoc); + + return ( +
  • + + {param.getName()} + {" "} + + +
  • + ); + })} +
+ +
    +
  • + + +
  • +
+ + ); + }) +} diff --git a/src/components/index.ts b/src/components/index.ts index 0a984a493a12c4c..06a0115982b9b39 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -66,6 +66,7 @@ export { default as Width } from "./Width.astro"; export { default as WorkersArchitectureDiagram } from "./WorkersArchitectureDiagram.astro"; export { default as WorkersIsolateDiagram } from "./WorkersIsolateDiagram.astro"; export { default as WorkersTemplates } from "./WorkersTemplates.astro"; +export { default as WorkersTypesInterface } from "./WorkersTypesInterface.astro"; export { default as YouTube } from "./YouTube.astro"; export { default as YouTubeVideos } from "./YouTubeVideos.astro"; diff --git a/src/content/docs/style-guide/components/workers-types-interface.mdx b/src/content/docs/style-guide/components/workers-types-interface.mdx new file mode 100644 index 000000000000000..7c3b31025b58b41 --- /dev/null +++ b/src/content/docs/style-guide/components/workers-types-interface.mdx @@ -0,0 +1,37 @@ +--- +title: Workers Types Interface +styleGuide: + component: WorkersTypesInterface +--- + +:::caution + +This component should be considered a work-in-progress and there may be parts of an interface not properly represented yet. + +::: + +This component uses [`ts-morph`](https://ts-morph.com/) to generate documentation about the methods on an interface from `@cloudflare/workers-types`, including their parameters and return types. + +## Import + +```mdx +import { WorkersTypesInterface } from "~/components"; +``` + +## Usage + +```mdx live +import { WorkersTypesInterface } from "~/components"; + + +``` + +## `` Props + +### `name` + +**required** + +**type:** `string` + +The name of the TypeScript interface.