diff --git a/blog/2025-11-22-welcome/index.md b/blog/2025-11-22-welcome/index.md new file mode 100644 index 0000000..6c9e555 --- /dev/null +++ b/blog/2025-11-22-welcome/index.md @@ -0,0 +1,11 @@ +--- +slug: welcome +title: Welcome +--- + +TODO: + +- Introduce the background of API Studio: why and when this project was + initiated. +- What problems exist with current tools, what issues they failed to address, + and how API Studio provides a solution. diff --git a/docs/configs/_category_.json b/docs/configs/_category_.json index 9e03e67..49be94f 100644 --- a/docs/configs/_category_.json +++ b/docs/configs/_category_.json @@ -1,6 +1,6 @@ { "label": "Configs", - "position": 2, + "position": 3, "link": { "type": "generated-index", "description": "Workspace config files" diff --git a/docs/configs/api-client/_category_.json b/docs/configs/api-client/_category_.json new file mode 100644 index 0000000..8509b5f --- /dev/null +++ b/docs/configs/api-client/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "API Client", + "position": 2, + "link": { + "type": "generated-index", + "description": "API client configs" + } +} diff --git a/docs/configs/collection.md b/docs/configs/api-client/collection.md similarity index 97% rename from docs/configs/collection.md rename to docs/configs/api-client/collection.md index d91aed3..1cfd609 100644 --- a/docs/configs/collection.md +++ b/docs/configs/api-client/collection.md @@ -1,5 +1,6 @@ --- sidebar_position: 2 +title: Collection --- # Collection Config @@ -89,5 +90,5 @@ All variables can be reassigned at run-time using `requestMiddleware.js`. ## `requests` -A list of request definitions. See [Request config](/docs/configs/request) for +A list of request definitions. See [Request config](/docs/configs/api-client/request) for details. diff --git a/docs/configs/request.md b/docs/configs/api-client/request.md similarity index 99% rename from docs/configs/request.md rename to docs/configs/api-client/request.md index 7e88494..0e4cc77 100644 --- a/docs/configs/request.md +++ b/docs/configs/api-client/request.md @@ -1,5 +1,6 @@ --- sidebar_position: 3 +title: Request --- # Request Config diff --git a/docs/configs/mock-servers/_category_.json b/docs/configs/mock-servers/_category_.json new file mode 100644 index 0000000..2e5a7b9 --- /dev/null +++ b/docs/configs/mock-servers/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Mock Servers", + "position": 3, + "link": { + "type": "generated-index", + "description": "Mock servers configs" + } +} diff --git a/docs/configs/mock-servers/route-case-matchers.md b/docs/configs/mock-servers/route-case-matchers.md new file mode 100644 index 0000000..de77a7e --- /dev/null +++ b/docs/configs/mock-servers/route-case-matchers.md @@ -0,0 +1,57 @@ +--- +sidebar_position: 2 +title: Case Matchers +--- + +# Case matchers + +Case matchers are used for the mock server to match the request context. + +We use the same naming as the +[Jest Asymmetric Matchers](https://jestjs.io/docs/expect#asymmetric-matchers) +and almost have the same behavior. + +## `anything()` + +`anything()` matches anything but `null`. + +```json title="case" +{ + "body": { + "name": "{{anything()}}" + } +} +``` + +## `any(type)` + +`any(type)` matches anything that is the given `type`. + +`type` includes: `Number`, `String`, `Array`, `Object` + +```json title="case" +{ + "body": { + "id": "{{any(Number)}}", + "name": "{{any(String)}}", + "accesses": "{{any(Array)}}" + } +} +``` + +## `arrayContaining(array)` + +`arrayContaining(array)` matches a received array which contains all of the +elements in the expected array. + +```json title="case" +{ + "body": { + "categories": "{{arrayContaining([1, 2])}}" + } +} +``` + +--- + +To Continue... diff --git a/docs/features/_category_.json b/docs/features/_category_.json new file mode 100644 index 0000000..6820fd3 --- /dev/null +++ b/docs/features/_category_.json @@ -0,0 +1,7 @@ +{ + "label": "Features", + "position": 2, + "link": { + "type": "generated-index" + } +} diff --git a/docs/features/api-client.md b/docs/features/api-client.md new file mode 100644 index 0000000..7b78a27 --- /dev/null +++ b/docs/features/api-client.md @@ -0,0 +1,28 @@ +--- +sidebar_position: 1 +title: API Client +--- + +# API Client + +The API Client is where you run HTTP requests defined in your workspace configs +and inspect the results. + +Instead of building requests through a UI, you describe them in JSON files +(`collections/*.json`) and let Api Studio execute them. This keeps your API +usage close to your code and easy to version-control. + +## What it does + +- Sends HTTP requests based on your request config: + - Method, URL, query, headers, body. + - Resolved with variables from workspace, environment, collection, and + request. +- Applies `requestMiddleware` (if present) before the request is sent: + - Last chance to modify the request. + - Optionally handle auth, logging, or custom workflows. +- Executes the request and shows: + - Status code and status text. + - Response headers. + - Response body. + - Timing information. diff --git a/docs/features/mock-servers.md b/docs/features/mock-servers.md new file mode 100644 index 0000000..ae9813c --- /dev/null +++ b/docs/features/mock-servers.md @@ -0,0 +1,83 @@ +--- +sidebar_position: 2 +title: Mock Servers +--- + +# Mock servers + +Mock servers let you describe local **HTTP/HTTPS** endpoints in JSON and get +dynamic, rule-based responses without a real backend. + +## Case-based routing + +Each route can define multiple **cases**. +The incoming request is matched against these cases (method, path, query, body, +etc.), and the first match decides the response. This makes it easy to model +different scenarios for the same endpoint. + +## Jest-style matchers + +Request matching supports a Jest-like syntax, such as: + +- `any(Constructor)` +- `stringMatching(...)` +- `stringContaining(...)` + +This lets you write expressive conditions (for example “any string containing +`foo`”) directly in your JSON config, without extra code. + +### Example + +```json +{ + "cases": [ + { + "request": { + "query": { + "name": "{{stringContaining('foo')}}" + } + }, + "response": { + "body": { + "result": "ok" + } + } + }, + { + "request": { + "body": { + "level": "{{any(Number)}}" + } + }, + "response": "@file:../data/welcome.json" + } + ] +} +``` + +## Flexible responses and proxying + +For a matched case you can: + +- Return an inline JSON response. +- Load the response from a file (for example `@file:../data/welcome.json`). +- Or **forward** the request to another server, acting as a lightweight proxy + server. + +This combination lets you mix mocked behaviour with real upstream services in a +single, versioned workspace. + +### Proxy Config Example + +```json +{ + "name": "AWS Sam Local", + "method": "GET", + "path": "aws", + "cases": [ + { + "forward": "https://localhost:3000" + } + ] +} +``` diff --git a/docs/quickstart.md b/docs/quickstart.md index 116bea2..7298b38 100644 --- a/docs/quickstart.md +++ b/docs/quickstart.md @@ -40,8 +40,3 @@ This file defines the workspace configuration. It must: Launch **Api Studio**, click **"Open Workspace..."**, and select the folder you just created. - -## 3. Next Steps - -Check out the [Configs](/docs/category/configs) to learn how to create workspace -config, collections, and requests. diff --git a/docs/scripts/_category_.json b/docs/scripts/_category_.json index 8a3acb5..2b33316 100644 --- a/docs/scripts/_category_.json +++ b/docs/scripts/_category_.json @@ -1,6 +1,6 @@ { "label": "Scripts", - "position": 3, + "position": 5, "link": { "type": "generated-index" } diff --git a/docusaurus.config.ts b/docusaurus.config.ts index 3cefcbb..b81b971 100644 --- a/docusaurus.config.ts +++ b/docusaurus.config.ts @@ -43,7 +43,18 @@ const config: Config = { sidebarPath: './sidebars.ts', // Please change this to your repo. // Remove this to remove the "edit this page" links. - editUrl: 'https://github.com/hanlogy/api-studio/', + // editUrl: 'https://github.com/hanlogy/api-studio/', + }, + blog: { + showReadingTime: true, + feedOptions: { + type: ['rss', 'atom'], + xslt: true, + }, + // Useful options to enforce blogging best practices + onInlineTags: 'warn', + onInlineAuthors: 'warn', + onUntruncatedBlogPosts: 'warn', }, theme: { customCss: './src/css/custom.css', @@ -69,15 +80,16 @@ const config: Config = { type: 'docSidebar', sidebarId: 'tutorialSidebar', position: 'left', - label: 'Tutorial', + label: 'Docs', }, + { to: '/blog', label: 'Blog', position: 'left' }, { - href: 'https://github.com/hanlogy/api-studio/issues', + href: 'https://github.com/hanlogy/app.api-studio/discussions', label: 'Support', position: 'left', }, { - href: 'https://github.com/hanlogy/api-studio', + href: 'https://github.com/hanlogy/app.api-studio', label: 'GitHub', position: 'right', },