From b6788a60f329d693e2d28cf8eee937c1fbc918c4 Mon Sep 17 00:00:00 2001 From: Yohe-Am <56622350+Yohe-Am@users.noreply.github.com> Date: Wed, 22 May 2024 17:29:06 +0300 Subject: [PATCH] docs: `/docs/concepts/features-overview/` (#725) - Re-does the feature overview page of the documentation. ## Summary by CodeRabbit - **New Features** - Added a "Features Roadmap" component to the website, displaying a list of features with details and links. - **Documentation** - Updated various guides and reference documents to improve clarity and presentation of code examples. - Added new sections for various features such as Typegate, Typegraph, Runtimes, Prisma, Auth, Tooling, and SDK. - **Bug Fixes** - Corrected a typo in the GraphQL runtimes reference documentation. - **Refactor** - Replaced `SDKTabs` and `TabItem` components with `TGExample` for better code example presentation. - Adjusted the `MiniQL` component to handle optional properties and default settings. --------- Signed-off-by: Yohe-Am <56622350+Yohe-Am@users.noreply.github.com> Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- .../docs/concepts/features-overview/index.mdx | 810 +++++++++++++++++- .../docs/guides/external-functions/index.mdx | 52 +- website/docs/guides/rest/index.mdx | 25 +- .../docs/guides/securing-requests/index.mdx | 49 +- .../docs/reference/runtimes/graphql/index.mdx | 6 +- website/shared/s3/index.mdx | 17 - website/src/components/MiniQL/index.tsx | 69 +- website/src/pages/features/index.tsx | 97 +++ 8 files changed, 938 insertions(+), 187 deletions(-) create mode 100644 website/src/pages/features/index.tsx diff --git a/website/docs/concepts/features-overview/index.mdx b/website/docs/concepts/features-overview/index.mdx index 52c7d3d8e6..c0539c86ad 100644 --- a/website/docs/concepts/features-overview/index.mdx +++ b/website/docs/concepts/features-overview/index.mdx @@ -2,54 +2,814 @@ sidebar_position: 1 --- +import Features from "../../../src/pages/features"; +import TGExample from "@site/src/components/TGExample"; +import Link from "@docusaurus/Link"; +import CodeBlock from "@theme/CodeBlock"; + +# Features + +:::info Suggestions + +We're taking any and all kinds of feature requests, suggestions and recommendations. Please direct them kindly to the github [ticket](https://github.com/metatypedev/metatype/issues) or better yet [discussion](https://github.com/metatypedev/metatype/discussions/) boards. Thank you! + +::: + +## Typegate + + + Expose select materializers in your graph through a GraphQL API. + These root-materializers will serve as the entry point to your graph for any incoming request. + The typegraph model is a great fit for GraphQL semantics and this is the best supported way to consume typegraphs. + + ), + }, + { + title: "GraphQL Subscriptions", + status: "future", + link: "https://github.com/metatypedev/metatype/issues/726", + body: ( + <> + Get real-time data to clients. + + ), + }, + ], + [ + { + title: "REST API", + status: "complete", + link: "/docs/guides/rest", + body: ( + <> + You can expose select root materializers through a simple REST API. + This is handy to serve endpoints for clients that are not GraphQl capable, even though it hampers access to some typegraph features. + Inputs will be sourced from either HTTP bodies or search parameters according to HTTP verb. + + ), + }, + { + title: "gRPC API", + status: "future", + link: "/docs/reference/typegate", + body: ( + <> + Support to expose the typegraph through a gRPC API. + + ), + }, + ], + [ + { + title: "Cron triggers", + status: "future", + link: "/docs/reference/typegate", + body: ( + <> + Execute materializers at certain time intervals. + Useful for cleanup jobs. + + ), + }, +
+ ], + [ + { + title: "Rate-limiting", + status: "complete", + link: "/docs/reference/typegate/cors", + body: ( + <> + Rate-limit parts of your graph to minimize abuse. + The limits can be configured granularly for each materializer and for custom time windows. + Use custom request identifiers, in addition to ip addresses, to track limits counters. + + ), + }, + { + title: "CORS", + status: "complete", + link: "/docs/reference/typegate/cors", + body: ( + <> + Specify cross-origin request rules to control which domains can access your API from within a browser. + Prevents abuse from websites trying to use your API without permission. + + ), + }, + ], + [ + { + title: "Single-node", + status: "complete", + link: "/docs/reference/typegate/synchronization", + body: ( + <> + The typegate can be run as a single node mode for simple deployments and using the filesystem as its artifact store. + Useful for local development and testing. + + ), + }, + { + title: "Multi-node", + status: "complete", + link: "/docs/reference/typegate/synchronization", + body: ( + <> + Deploy multiple instances of the typegate to distribute loads across machines and scale horizontally. + You'll only need a Redis compatible key-value cache, an S3 compatible object store, and your favorite load-balancer in front of the instances to get it going. + This mode is recommended for production deployments even if only a single node is used. + + ), + } + ], + ]} +/> + +## Typegraph + +, + ], + [ + { + title: "Scalar types", + status: "complete", + link: "/docs/reference/types#scalar-types", + body: ( + <> + The primitive types integer, float, boolean, string and file. + All data that flows through a typegraph reduces down to these types. + + ), + }, + { + title: "Type constraints", + status: "complete", + link: "/docs/reference/types/injections", + body: ( + <> + Declare types in your graph that are subset of primitives like string and integers by using regular expressions or min/max limits. + Useful to validate incoming data even more and distribute invariants through your app. + + ), + }, + ], + [ + { + title: "Composite types", + status: "complete", + link: "/docs/reference/types#scalar-types", + body: ( + <> + Support for struct, list, union, either and optional types. + These allow you to represent types equivalent to most modern type systems. + + ), + }, + { + title: "Injections", + status: "complete", + link: "/docs/reference/types/injections", + body: ( + <> + Injections resolve part of your graph inline instead of from materializers or provide defaults for incoming request data. + This can be used to set static values or source them from the context, other parts of the graph...etc. + + ), + }, + ], + [ + { + title: "Materializers (Functions)", + status: "complete", + link: "/docs/reference/types/functions", + body: ( + <> + Nodes in your typegraph that represent data to be resolved after running some logic on a Runtime. + + ), + }, + { + title: "Materializer chaining", + status: "future", + link: "https://github.com/metatypedev/metatype/issues/721", + body: ( + <> + Compose materializers together by feeding the output of one as the input of another. + Encourages code reuse by allowing one to extract common middleware logic from each materializer, all within the typegraph layer. + + ), + }, + ], + [ + { + title: (reduce), + status: "complete", + link: "/docs/reference/types/parameter-transformations#funcreducetree", + body: ( + <> + reduce is useful to transform materializer input types so that only certain struct fields are used, discarding the others. + Required fields can be hidden from the user and can instead be injected from the request's context or a static default. + This is useful for remixing generated or core domain types to more targeted forms appropriate for a materializer. + + ), + }, + { + title: (apply), + status: "complete", + link: "/docs/reference/types/parameter-transformations#funcapplytree", + body: ( + <> + apply allows the flattening of deeply nested types materializer input types to something friendlier. + Injection can also be used to substitute required fields in the original type from another source. + + ), + }, + ], + [ + { + title: "Imports", + status: "future", + link: "https://github.com/metatypedev/metatype/issues/722", + body: ( + <> + Imports will allow graphs to include nodes from other API descriptions like GraphQL, OpenAPI, gRPC and database schemas. + These APIs can then be consumed in a typesafe manner through the GraphQL and Http runtimes. + + ), + }, + { + title: "Secrets", + status: "complete", + link: "#", + body: ( + <> + First-class support for secrets to ease runtime substitution of sensetive values. + API keys or dynamic values only discovrable after deployment, this is how you get them into your app. + + ), + }, + ], + ]} +/> + +## Runtimes + + + Write materializers that execute pieces of TypeScript code on a Deno worker. + Includes easy access to ESM and libraries through standard Deno features. + + ), + }, + ], + [ + , + ], + [ + { + title: "Python runtime", + status: "beta", + link: "/docs/reference/runtimes/python", + body: ( + <> + Implement materializers that execute python functions in code snippets or on disk modules. + + ), + }, + ], + [ + +{`from typegraph import typegraph, Policy, t, Graph +from typegraph.runtimes.deno import PythonRuntime + +@typegraph() +def example_python(g: Graph): + public = Policy.public() + python = PythonRuntime() + + g.expose( + public, + add=t.func( + t.struct({"a": t.integer(), "b": t.integer()}), + t.integer(), + # we can provide the code inline using lambdas + python.from_lambda(lambda x: x["a"] + x["b"]), + ), + sayHello=python.import_( + t.struct({"name": t.string()}), + t.string(), + # point to pythoin a file on disc + module="hello.py", + name="say_hello" + ), + ) +}`} + + ], + [ + { + title: "S3 runtime", + status: "complete", + link: "/docs/reference/runtimes/s3", + body: ( + <> + Store large blobs in S3 compatible object stores. + This includes support for GraphQL file uploads and presigned URLs making working with images and large uploads a breeze. + + ), + }, + { + title: "Temporal runtime", + status: "complete", + link: "/docs/reference/runtimes/temporal", + body: ( + <> + Kick off and query Temporal workflows from a typegraph. + Temporal is a durable execution engine that can be used to implement long-running, failure-resistant business processes. + + ), + }, + { + title: "Wasm runtime", + status: "beta", + link: "/docs/reference/runtimes/wasm", + body: ( + <> + Make materializers that use WASM components to implement their logic. + Write core-wasm or wasi 0.2 based wasm components in languages like Rust, Python and Javascript + to power all your custom functions. + + ), + }, + ], + [ + { + title: "GraphQL runtime", + status: "complete", + link: "/docs/reference/runtimes/graphql", + body: ( + <> + Include external GraphQL APIs as part of your typegraph. + This runtime provides materializers that resolve the data by querying an external GraphQL API. + + ), + }, + { + title: "Http runtime", + status: "complete", + link: "/docs/reference/runtimes/http", + body: ( + <> + Include external Http APIs as part of your typegraph. + Source the data for your graph using external HTTP requests. + + ), + }, + ], + [ + { + title: "Random runtime", + status: "complete", + link: "/docs/reference/runtimes/random", + body: ( + <> + Materializers to generate random data based on your types. + Useful for quickly throwing together an API and testing. + + ), + }, + { + title: "gRPC runtime", + status: "future", + link: "https://github.com/metatypedev/metatype/issues/723", + body: ( + <> + Include external gRPC APIs as part of your typegraph. + + ), + }, + ], + ]} +/> + +### Prisma + +Access a myriad of databases directly from your typegraph. Run queries, mange it's schema, the full orm featureset. + +, + ], + [ + { + title: "Relational schemas", + status: "complete", + link: "/docs/reference/runtimes/prisma#relationships", + body: ( + <> + Use the types in your graph to declare and manage relational schemas to be used on your databse. + This means support for primary keys, unique constraints, one-to-one, one-to-many, many-to-many relationships...etc. + + ), + }, + { + title: "CRUD queries", + status: "complete", + link: "/docs/reference/runtimes/prisma#generators", + body: ( + <> + Generate easy materializers for common create, update, read and delete queries. + Includes nested filtering and aggregration paramters for efficent and targeted requests. + + ), + }, + { + title: "Raw queries", + status: "complete", + link: "/docs/reference/runtimes/prisma#raw-query", + body: ( + <> + Drop down to raw SQL queries for cases not covered by the CRUD generators. + Useful to access unique features native to your database or craft extra efficient queries. + + ), + }, + ], + [ + { + title: "PostgreSQL support", + status: "complete", + link: "/docs/reference/runtimes/prisma", + body: ( + <> + Support for PostgreSQL, a modern and established DBMS. + + ), + }, + { + title: "Beta databases", + status: "beta", + link: "https://github.com/metatypedev/metatype/issues/724", + body: ( + <> + MySQL, MariaDB, AWS Aurora, AWS Aurora Serverless, Microsoft SQL Server, Azure SQL, MongoDB, CockroachDB. + + ), + }, + ] + ]} +/> + +## Auth + + + Policies are simple functions that take the request as input and return values to signal whether it's allowed/denied access. + They can be attached to any materializer in the graph and are evaluated right before the request triggers one. + They compose well and are the primary authorization primitive available to typegraphs. + + ), + }, + ], + [ + , + ], + [ + { + title: "Basic authentication", + status: "complete", + link: "/docs/reference/typegate/authentication#basic-authentication", + body: ( + <> + Requests can authenticate themselves using Basic HTTP headers. + Simple but useful for getting started or protecting admin only requests. + + ), + }, + , + ], + [ + { + title: "JWT authentication", + status: "complete", + link: "/docs/reference/typegate/authentication#jwt-authentication", + body: ( + <> + Json Web Tokens can be used to attach more authentication and context information to requests. + The data in the tokens can then be used by policies to make authorization decisions. + + ), + }, + , + ], + [ + { + title: "Oauth2 authorization", + status: "complete", + link: "/docs/reference/typegate/authentication#oauth2-authorization", + body: ( + <> + Use the Oauth2 scheme to implement social-sign in from common identity providers like Github, Meta and Google. + + ), + }, + , + ], + ]} +/> + + +## Tooling + + + Full-featured CLI to aid development and manage typegraph deployments on the typegate. + Supports watch mode to aid rapid-iteration, including support for interactive database migration management. + Bundles the typegate within it making the CLI all one needs to get started. (And a text editor, of course.) + + ), + }, + ], + [ + +{`❯ meta --help at 02:03:36 +Declarative API development platform. Build backend components with WASM/Typescript/Python, no matter where and how your (legacy) systems are. + +Usage: meta [OPTIONS] [COMMAND] + +Commands: + serialize Serialize the typegraphs defined in the specified python file(s) into JSON + dev Push typegraph(s) with development mode features enabled + deploy Push typegraph(s) to typegate + undeploy Undeploy typegraph(s) from typegate + gen Access metagen generators + upgrade Upgrade + completion Generate shell completion + doctor Troubleshoot the installation + new Create a new Metatype project + typegate Access a minimal deno CLI + help Print this message or the help of the given subcommand(s) + +Options: + --version + -v, --verbose... Increase logging verbosity + -q, --quiet... Decrease logging verbosity + -C, --dir [default: .] + --config path to the config file + -h, --help Print help +`} + + ], + [ + { + title: "Metagen", + status: "beta", + link: "#", + body: ( + <> + Code generation suite that supports Rust, Python and Typescript. + Generate types from your graph and other helper functions for authoring custom functions for the Wasm, Python and Deno runtimes respectively. + Can be accessed through the CLI under the gen subcommand or through the different SDKs. + + ), + }, + { + title: "Meta LSP", + status: "beta", + link: "/docs/reference/meta-lsp", + body: ( + <> + Extension for your IDE to help authoring of typegraphs. + Supports VSCode as of now. + + ), + }, +
+ ], + [ + { + title: "Docker images", + status: "complete", + link: "https://github.com/orgs/metatypedev/packages/container/package/typegate", + body: ( + <> + The typegate is primarily distributed as a docker image for deployment as a container. + All the available configuration environment variables can be found here. + + ), + }, + { + title: "Helm charts", + status: "complete", + link: "/docs/guides/self-hosting", + body: ( + <> + Helm charts are published to ease installation of a typegate deployment in your Kubernetes cluster. + + ), + }, + ], + [ + + {`docker run --rm --pull always \\ + -p 7890:7890 \\ + -e TG_SECRET=$(openssl rand -base64 64 | tr -d '\\n') \\ + -e TG_ADMIN_PASSWORD="password" \\ + ghcr.io/metatypedev/typegate:latest`} + + ] + ]} +/> + +## SDK + + + Use typescript to author typegraphs and access other SDK tooling. + Supports Node and compatible runtimes like Deno and Bun. + + ), + }, + { + title: "Python SDK", + status: "complete", + link: "http://localhost:3000/docs/reference/typegate#environment-variables", + body: ( + <> + Use Python to author typegraphs and access other SDK tooling. + + ), + }, + ], + [ + { + title: "Deployments", + status: "complete", + link: "/docs/reference/programmatic-deployment", + body: ( + <> + Programmatically upload your typegraphs to the typegate from within the SDK. + Useful for writing tests or building on top of the Metatype platform. + + ), + }, + { + title: "Migrations", + status: "beta", + link: "/docs/reference/programmatic-deployment", + body: ( + <> + Programmaticaly manage necessary migrations returned by the Prisma runtime. + Useful for writing tests or building on top of the Metatype platform. + + ), + }, + ], + [ + { + title: "Codegen", + status: "beta", + link: "/docs/reference/programmatic-deployment", + body: ( + <> + Access metagen through the SDK directly to generate type declarations and other helpful code. + Useful for testing and to build custom workflows/tooling. + + ), + }, +
, + ], + ]} +/> + + diff --git a/website/docs/guides/external-functions/index.mdx b/website/docs/guides/external-functions/index.mdx index dc1cbb18db..15c2420b1a 100644 --- a/website/docs/guides/external-functions/index.mdx +++ b/website/docs/guides/external-functions/index.mdx @@ -2,8 +2,6 @@ sidebar_position: 50 --- -import SDKTabs from "@site/src/components/SDKTabs"; -import TabItem from "@theme/TabItem"; import TGExample from "@site/src/components/TGExample"; import CodeBlock from "@theme-original/CodeBlock"; @@ -21,28 +19,13 @@ Custom functions are commonly used for: The following example uses the `DenoRuntime` to respond to requests and define a policy. - - - - - - - - - - - - Note that for the `fib` root materializer, we're using a typescript module in an external file. Here's what `scripts/fib.ts` looks like: @@ -63,29 +46,15 @@ The following feature is currently only implemented for the `DenoRuntime`. ::: On some runtimes, custom functions are passed the context object along with the materializer inputs. -This object provides access to all kind of information about the context in which the function is running. +This object provides access to all kinds of information about the context in which the function is running. The following example illustrates availaible fields: - - - - - - - - - - - Note, the typescript version of the sample uses a closure instead of a string snippet to define the function. This is a simple syntax sugar availaible when using `DenoRuntime` through the typescript sdk or the `PythonRuntime` the python one. @@ -102,26 +71,13 @@ The primary way of doing this is by sending GraphqQl queries from within your fu On the `DenoRuntime`, to make this easier, there's a `gql` object passed to all functions. The following exapmle illustrates how it functions: - - - - - - - - - - And `scripts/createVote.ts` looks like: diff --git a/website/docs/guides/rest/index.mdx b/website/docs/guides/rest/index.mdx index 2cc967c7ff..6622b4595e 100644 --- a/website/docs/guides/rest/index.mdx +++ b/website/docs/guides/rest/index.mdx @@ -2,9 +2,8 @@ sidebar_position: 50 --- -import SDKTabs from "@site/src/components/SDKTabs"; -import TabItem from "@theme/TabItem"; import CodeBlock from "@theme-original/CodeBlock"; +import TGExample from "@site/src/components/TGExample"; # Write REST endpoints @@ -12,23 +11,15 @@ The root materializers, the ones we expose from our typegraphs, are served throu In addition, we can also expose [REST](https://en.wikipedia.org/wiki/REST) APIs using the `rest` method. The method takes GraphQl queries and provides RESTly endpoints for them. - - + -{require("!!code-loader!../../../../examples/typegraphs/example_rest.ts").content} - - - - - -{require("../../../../examples/typegraphs/example_rest.py").content} - - - - -The effect of the root materializer accessed in the query determines the HTTP verb used and the mapping can be found [here](/docs/reference/types/functions#effects). +The effect of the root materializer accessed in the query determines the HTTP verb used, and the mapping can be found [here](/docs/reference/types/functions#effects). There's also an OpenAPI schema generated from the rest endpoints served under `{typegate_url}/{typegraph}/rest/_schema`. -A browser based explorer for the OpenAPI schema is served under `{typegate_url}/{typegraph}/rest` as well. +A browser-based explorer for the OpenAPI schema is served under `{typegate_url}/{typegraph}/rest` as well. {/* todo: link to the expample's redoc*/} diff --git a/website/docs/guides/securing-requests/index.mdx b/website/docs/guides/securing-requests/index.mdx index aa0666398a..43903fb2d2 100644 --- a/website/docs/guides/securing-requests/index.mdx +++ b/website/docs/guides/securing-requests/index.mdx @@ -2,10 +2,9 @@ sidebar_position: 50 --- -import TGExample from "@site/src/components/TGExample"; import Cors from "@site/shared/cors/index.mdx"; -import SDKTabs from "@site/src/components/SDKTabs"; import TabItem from "@theme/TabItem"; +import TGExample from "@site/src/components/TGExample"; # Secure your requests @@ -28,26 +27,10 @@ Basic authentication relies on a username and password pair. We specify the password through typegraph secrets with the format `BASIC_{username}`. In this case, the secret `BASIC_andim=password` is set. - - - - - - - - - - - - Note, the token is encoded in base64. Decoded, it'd read `andim:password`. @@ -95,25 +75,9 @@ typegates: BASIC_user: "user_pass" ``` - - - - - - - - - - - - -More than one policies can be attached to a single materalizer and combining policies allow for compositionaly defining our access control rules. -If a materalizer has more one policies, they are evaluated in turn and: +More than one policy can be attached to a single materalizer and combining policies allows for compositionaly defining our access control rules. +If a materalizer has more than one policy, they are evaluated in turn and: - If any one of attached policy returns `true`, the request immediately gains access. - If a policy returns `false`, the request is immediately denied access. diff --git a/website/docs/reference/runtimes/graphql/index.mdx b/website/docs/reference/runtimes/graphql/index.mdx index 8d6439a8d4..45107c2044 100644 --- a/website/docs/reference/runtimes/graphql/index.mdx +++ b/website/docs/reference/runtimes/graphql/index.mdx @@ -15,12 +15,12 @@ Update `typegraph.py` with the highlighted lines below: query={require("./graphql.graphql")} /> -Again, a few interesting happened here: +Again, a few interesting things happened here: 1. No migration has been run. The field `user` comes from another runtime and doesn't exist in the database. The typegate will orchestrate the query execution in all runtimes and minimize the work done. -2. The `from_parent` rule automatically fills the input type with the parent field named `uid`. The `g(·)` rule allows making named reference to another type and avoid circular reference. +2. The `from_parent` rule automatically fills the input type with the parent field named `uid`. The `g(·)` rule allows making named references to another type and avoids circular references. -Other type enforcement rules also exists: +Other type enforcement rules also exist: - `from_secret(key)` to fill the input type with the secret in the `TG_[typegraph name]_[key]` format - `from_context(·)` to fill the input type with content from the request context, such as JSON Web Token (JWT), etc. diff --git a/website/shared/s3/index.mdx b/website/shared/s3/index.mdx index 008b2a4ff8..fc222860a5 100644 --- a/website/shared/s3/index.mdx +++ b/website/shared/s3/index.mdx @@ -1,6 +1,4 @@ import TGExample from "@site/src/components/TGExample"; -import SDKTabs from "@site/src/components/SDKTabs"; -import TabItem from "@theme/TabItem"; import CodeBlock from "@theme-original/CodeBlock"; The [S3Runtime](/docs/reference/runtimes/s3) can be used to interact with object storage APIs that are S3 compatible. @@ -44,26 +42,11 @@ typegates: Our typegraph will then look something like: - - - - - - - - - - - - Peruse the [reference](/docs/reference/runtimes/s3) on the `S3Runtime` for more information. diff --git a/website/src/components/MiniQL/index.tsx b/website/src/components/MiniQL/index.tsx index 9ee77fca20..d6f1c16bbd 100644 --- a/website/src/components/MiniQL/index.tsx +++ b/website/src/components/MiniQL/index.tsx @@ -22,19 +22,19 @@ import { useSDK } from "../../states/sdk"; import TabItem from "@theme/TabItem"; export interface MiniQLProps { - typegraph: string; - query: ast.DocumentNode; code?: Array<{ content: string; codeLanguage?: string; codeFileUrl?: string; }>; + typegraph?: string; + query?: ast.DocumentNode; headers?: Record; variables?: Record; panel?: Panel; noTool?: boolean; defaultMode?: keyof typeof modes | null; - disablePlayground: boolean + disablePlayground?: boolean; } function Loader() { @@ -71,7 +71,7 @@ function MiniQLBrowser({ createGraphiQLFetcher({ url: `${tgUrl}/${typegraph}`, }), - [] + [], ); const [mode, setMode] = useState(defaultMode); @@ -80,23 +80,15 @@ function MiniQLBrowser({ // console.log(code); return (
- {defaultMode ? ( - - ) : null} - -
+ : null} +
- {!defaultMode || mode === "typegraph" ? ( + > + {disablePlayground || !defaultMode || mode === "typegraph" + ? (
- ) : null} - {!disablePlayground && (!defaultMode || mode === "playground") ? ( -
-
- -
+ ) + : null} + {!disablePlayground && (!defaultMode || mode === "playground") + ? ( + +
+
+ +
-
- - +
+ + +
-
- ) : null} -
- + + ) + : null} +
); } diff --git a/website/src/pages/features/index.tsx b/website/src/pages/features/index.tsx new file mode 100644 index 0000000000..ad66f83edd --- /dev/null +++ b/website/src/pages/features/index.tsx @@ -0,0 +1,97 @@ +// Copyright Metatype OÜ, licensed under the Elastic License 2.0. +// SPDX-License-Identifier: Elastic-2.0 + +/* eslint-disable @typescript-eslint/no-var-requires */ + +import React from "react"; +import "react-lite-youtube-embed/dist/LiteYouTubeEmbed.css"; +import Heading from "@theme/Heading"; +import CodeBlock from "@theme-original/CodeBlock"; +import Link from "@docusaurus/Link"; + +export default function FeaturesRoadmap( + props: { + rows: (React.JSX.Element | FeatureDeets | { + content: string; + path: string; + })[][]; + }, +): JSX.Element { + return ( +
+ {props?.rows?.map((row) => ( +
+ {row.map( + (item) => { + if ("title" in item) { + return ( +
+ +
+ ); + } + if ("content" in item) { + const split = item.path.split("."); + const lang = split[split.length - 1]; + return ( +
+ + {item.path.split("/").pop()} ↗ + + + {item.content} + +
+ ); + } + return
{item}
; + }, + )} +
+ ))} +
+ ); +} + +type FeatureDeets = { + title: React.JSX.Element | string; + status: "complete" | "beta" | "future"; + body: React.JSX.Element; + link: string; +}; +function Feature(props: FeatureDeets) { + const statusColor = { + complete: "text-green-500", + beta: "text-yellow-500", + future: "text-pink-500", + }; + return ( + +
+
+ {props.title} + + {props.status.toUpperCase()} + +
+
+ {props.body} +
+
+ + ); +}